home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / QUI / UTI / Feature Flick v 1.5.sea / CQuickTime.c < prev    next >
Text File  |  1992-10-21  |  113KB  |  4,278 lines

  1. /******************************************************************
  2.  "CQuickTime.c"
  3.  
  4.  by:    Apple Inc.,
  5.          as distributed on their "QuickTime" CD ROM disk
  6.  
  7.  converted to "C" & OOP by:        John A. Love, III
  8.                                  using Symantec's "THINK C", v 5.0.2
  9.  ******************************************************************/
  10.  
  11.  
  12.  
  13.  
  14. #include <Global.h>
  15. #include <Balloons.h>
  16. #include <Commands.h>
  17. #include <Constants.h>
  18. #include <Files.h>
  19. #include <GestaltEqu.h>
  20. #include <OSChecks.h>
  21. #include <Packages.h>
  22. #include <StandardFile.h>
  23. #include <TCLUtilities.h>
  24. #include <Traps.h>
  25. #include <CBartender.h>
  26. #include <CButton.h>
  27. #include <CClipboard.h>
  28. #include <CDecorator.h>
  29. #include <CDLOGDialog.h>
  30. #include <CFWDesktop.h>
  31. #include <CIntegerText.h>
  32. #include <CList.h>
  33.  
  34. #include "CmyMisc.h"
  35. #include "CQuickTime.h"        // includes "Movies.h"
  36.  
  37.  
  38. extern CApplication        *gApplication;
  39. extern CBartender        *gBartender;
  40. extern CBureaucrat        *gGopher;
  41. extern CClipboard        *gClipboard;
  42. extern CDecorator        *gDecorator;
  43. extern CDesktop            *gDesktop;
  44. extern short            gClicks;
  45. extern RgnHandle        gUtilRgn;
  46. extern OSType            gSignature;
  47. extern CursHandle        gWatchCursor;
  48. extern CCrsrHandle        niftyCameraCRSR;
  49. extern short            movieAppRes;
  50.  
  51.  
  52. Boolean                    ShiftKeyIsDownToSelectWholeMovie, FramesPreSelected,
  53.                         justActivated = false,        // For my CView::DispatchCursor…
  54.                         justSaved = false;
  55. CIconHandle                lightOn;
  56.  
  57.  
  58.  
  59. void    CMovieDesktop::IMovieDesktop (CBureaucrat *aSupervisor)        {
  60.  
  61.  
  62.     inherited::IFWDesktop(aSupervisor);
  63.     
  64. }    /* IMovieDesktop */
  65.  
  66.  
  67.  
  68. // OVERRIDE
  69. void    CMovieDesktop::DispatchCursor (Point where, RgnHandle mouseRgn)        {
  70.  
  71.  
  72.     UseResFile(movieAppRes);        // See comments within CMovieApp::StartUpAction
  73.     inherited::DispatchCursor (where, mouseRgn);
  74.     
  75. }    /* DispatchCursor */
  76.  
  77.  
  78.  
  79. // OVERRIDE
  80. void    CMovieClip::DeactivateWind (CWindow *theWindow)        {
  81. /* CClipboard::Toggle hides the clipboard window.  Otherwise, we
  82. ** could alter the contents of the actual Clipboard and would have
  83. ** no easy way to make the clipboard window's contents change while
  84. ** it was percolating in the background.  By hiding the clipboard
  85. ** window, we are forced to select "Show Clipboard" from the Edit
  86. ** Menu upon which the clipboard window's contents are updated.
  87. **
  88. ** Additionally, Toggle() toggles the Menu Item's text.  Also note
  89. ** that we do NOT override CDirector::ActivateWind.  Activate an
  90. ** invisible window -- get a life !!!                                */
  91.  
  92.  
  93.     Toggle();
  94.     
  95. }    /* DeactivateWind */
  96.  
  97.  
  98.  
  99. void    CMovieDLOGDir::IMovieDLOGDir (short dlogID)    {
  100.  
  101.  
  102.     inherited::IDLOGDirector(dlogID, gApplication);
  103.     
  104. }    /* IMovieDLOGDir */
  105.  
  106.  
  107.  
  108. // OVERRIDE
  109. void    CMovieDLOGDir::DoKeyDown (char theChar, Byte keyCode,
  110.                                   EventRecord *macEvent)    {
  111.  
  112.         CButton        *selectAllBtn;
  113.         
  114.         
  115.     if (macEvent->modifiers & cmdKey)
  116.     {
  117.         if (theChar == 'a' || theChar == 'A')
  118.         {
  119.             selectAllBtn = ((CDialog*) itsWindow)->FindButton(cmdSelectAll);
  120.             if (selectAllBtn)        selectAllBtn->SimulateClick();
  121.             ;
  122.             DoCommand(cmdSelectAll);
  123.         }
  124.         else
  125.         {
  126.             inherited::DoKeyDown(theChar, keyCode, macEvent);
  127.         }
  128.     }
  129.     
  130.     else    inherited::DoKeyDown(theChar, keyCode, macEvent);
  131.     
  132. }    /* DoKeyDown */
  133.  
  134.  
  135.  
  136. // OVERRIDE
  137. void    CMovieDLOGDir::DoCommand (long aCmd)    {
  138.  
  139.  
  140.     switch (aCmd)
  141.     {
  142.         case cmdOK:
  143.             EndDialog(cmdOK, TRUE);
  144.             /* Don't close Dialog here because eventually DoModalDialog
  145.             ** will call CButton::SimulateClick and there won't be a
  146.             ** Button CView around since the window will not exist.        */
  147.             break;
  148.             
  149.         case cmdCancel:
  150.             SysBeep(10);
  151.             EndDialog(cmdCancel, FALSE);
  152.             break;
  153.             
  154.         case cmdSelectAll:
  155.             EndDialog(cmdSelectAll, FALSE);
  156.             break;
  157.             
  158.         default:
  159.             inherited::DoCommand(aCmd);
  160.             break;
  161.     }
  162.     
  163. }    /* DoCommand */
  164.  
  165.  
  166.  
  167. void    CQuickTime::INoQuickTime (short DLOGid, CApplication *itsSupervisor)    {
  168.  
  169.         CDLOGDialog        *forShame = NULL;
  170.         
  171.     
  172.     inherited::IDocument(itsSupervisor, false /* NOT printable */);
  173.     
  174.     forShame = new (CDLOGDialog);
  175.     itsWindow = forShame;
  176.     forShame->IDLOGDialog(DLOGid, gDesktop, this);
  177.  
  178. }    /* INoQuickTime */
  179.  
  180.  
  181.  
  182. void    CQuickTime::DisplayNoQuickTime (void)    {
  183.  
  184.         long    finalTicks;
  185.         Rect    windR;
  186.         
  187.         
  188.     /* System 7 WIND resource automatically centers. 
  189.     ** Howsomever, IDLOGDialog calls AddDITLItems which
  190.     ** then calls IPicture for a picture Item.  Somewhere
  191.     ** amongst this chain, the above centering is undone: */
  192.     
  193.  // if ( !WINDResourceHasSystem7Field(itsWindow) )        {
  194.         
  195.             short    saveProcID = itsWindow->procID;
  196.             
  197.         itsWindow->SetModal(false);
  198.         // Gotta do this kludge because CenterWindow tests isModal
  199.         // AND the window's procID:
  200.         itsWindow->procID = 0;
  201.         gDecorator->CenterWindow(itsWindow);
  202.         itsWindow->procID = saveProcID;
  203.  // }
  204.     itsWindow->Select();
  205.     itsWindow->Prepare();
  206.     itsWindow->Update();
  207.     ;
  208.     SysBeep(10);
  209.     SysBeep(10);
  210.     ;
  211.     Delay(60, &finalTicks);
  212.     windR = itsWindow->macPort->portRect;
  213.     InvertRect(&windR);
  214.     Delay(30, &finalTicks);
  215.     InvertRect(&windR);
  216.     Delay(180, &finalTicks);
  217.             
  218. }    /* DisplayNoQuickTime */
  219.  
  220.  
  221.  
  222. void    CQuickTime::IQuickTime (CApplication *itsSupervisor)    {
  223.  
  224.         CWindow        *theWindow    = NULL;
  225.         CMovie        *theMovie    = NULL;
  226.         Rect        forStarters    = {0, 0, 150, 150};
  227.         
  228.         
  229.     inherited::IDocument(itsSupervisor, false /* NOT printable */);
  230.     
  231.     theWindow = new (CWindow);
  232.     itsWindow = theWindow;
  233.     
  234.     /* Un-titled window for now.  After we're finished here,
  235.     ** we will call OpenMovie(...) which will set the window's
  236.     ** title to the name of the Movie:                           */
  237.     
  238.     itsWindow->INewWindow(&forStarters, false /* NOT visible */,
  239.                           noGrowDocProc, false /* NOT floating */,
  240.                           true /* HAS goAway box */, gDesktop, this);
  241.     ;
  242.     /* CWindow::IWindowX sets minimum window size =
  243.     ** CWindow::sizeRect.topLeft = {100, 100}.  The
  244.     ** reason for the below value of 1 is that the
  245.     ** size of an empty Movie = {1, 1, 1, 1}.  The
  246.     ** minimum value = 112 was empirically determined. */
  247.     itsWindow->sizeRect.top = 1;
  248.     itsWindow->sizeRect.left = 112;
  249.     
  250.     theMovie = new (CMovie);
  251.     theMovie ->IMovie(itsWindow, this);
  252.     ;
  253.     itsMovie = theMovie;
  254.     itsMainPane = itsMovie;
  255.     itsGopher = itsMovie;
  256.     savedMovie = nil;
  257.     
  258.     /* For some reason, if my Help Balloon is showing
  259.     ** it will disappear and will NOT re-appear:      */
  260.     CView::cCurrHelpView = NULL;
  261.     CView::cLastHelpView = NULL;
  262.  
  263. }    /* IQuickTime */
  264.  
  265.  
  266.  
  267. void    CQuickTime::INewQuickTime (CApplication *itsSupervisor)    {
  268.  
  269.         CWindow                *theWindow    = NULL;
  270.         CMovie                *theMovie    = NULL;
  271.         Rect                forStarters = {0, 0, 150, 150};
  272.         short                numWindows, saveProcID;
  273.         Str255                Untitled    = "\pUntitled", numString, newTitle;
  274.         
  275.         
  276.     inherited::IDocument(itsSupervisor, false /* NOT printable */);
  277.     
  278.     theWindow = new (CWindow);
  279.     itsWindow = theWindow;
  280.     // Un-titled window for now.  Below we set title based on window count:
  281.     itsWindow->INewWindow(&forStarters, false /* NOT visible */,
  282.                           noGrowDocProc, false /* NOT floating */,
  283.                           true /* HAS goAway box */, gDesktop, this);
  284.     ;
  285.     /* CWindow::IWindowX sets minimum window size =
  286.     ** CWindow::sizeRect.topLeft = {100, 100}.  The
  287.     ** reason for the below value of 1 is that the
  288.     ** size of an empty Movie = {1, 1, 1, 1}.  The
  289.     ** minimum value = 112 was empirically determined. */
  290.     itsWindow->sizeRect.top = 1;
  291.     itsWindow->sizeRect.left = 112;
  292.     
  293.     theMovie = new (CMovie);
  294.     theMovie ->IMovie(itsWindow, this);
  295.     ;
  296.     itsMovie = theMovie;
  297.     itsMainPane = itsMovie;
  298.     itsGopher = itsMovie;
  299.     savedMovie = nil;
  300.     
  301.     /* Window title is used as part of new file's FSSpec record that
  302.     ** is created within DoSave.  In this manner, CDocument's
  303.     ** ConfirmClosing method places the window's new title in the
  304.     ** displayed ALeRT if you try to close the window or quit the
  305.     ** application without saving any changes to the Movie.            */
  306.     
  307.     numWindows = ++(gDecorator->wCount);
  308.     NumToString(numWindows, numString);
  309.     CopyPString(Untitled, newTitle);
  310.     ConcatPStrings(newTitle, "\p - ");
  311.     ConcatPStrings(newTitle, numString);
  312.     itsWindow->SetTitle(newTitle);
  313.     
  314.     // Make the empty Movie look like a Movie:
  315.     
  316.     itsMovie->NeewMovie();                // Calls NeewController() to do just that.
  317.     
  318.     CView::cCurrHelpView = NULL;
  319.     CView::cLastHelpView = NULL;    
  320.  
  321.     /* We'll center the window for now ... however, when we later paste
  322.     ** a Movie, we'll temporarily hide it so we can invisibly re-size
  323.     ** the window and THEN re-show it.  After re-showing, the window's
  324.     ** topLeft corner retains the value it had after it's centered below: */
  325.     
  326.     saveProcID = itsWindow->procID;
  327.     itsWindow->SetModal(false);
  328.     itsWindow->procID = 0;
  329.     gDecorator->CenterWindow(itsWindow);
  330.     itsWindow->procID = saveProcID;
  331.             
  332. }    /* INewQuickTime */
  333.  
  334.  
  335.  
  336. void    CQuickTime::DisplayQuickTime (void)        {
  337.         
  338.         
  339.     itsWindow->Select();
  340.     itsWindow->Prepare();
  341.  
  342. }    /* DisplayQuickTime */
  343.  
  344.  
  345.  
  346. void    CQuickTime::ClearQuickTime (void)    {
  347.         
  348.             
  349.     itsMovie->DisposMoovie();                    /* Sets moov = nil. */
  350.     itsMovie->DisposController();                /* Sets mc     = nil. */
  351.     if (savedMovie != nil) /* for reverting */        {
  352.         if (GetMovieDuration(savedMovie) > 0)    {
  353.             DisposeMovie(savedMovie);
  354.             FailOSErr( GetMoviesError() );
  355.         }
  356.         savedMovie = nil;
  357.     }
  358.     
  359. }    /* ClearQuickTime */
  360.  
  361.  
  362.  
  363. // OVERRIDE
  364. void    CQuickTime::Dispose (void)    {
  365.  
  366.     
  367.     if (itsMovie != NULL)    ClearQuickTime();
  368.     
  369.     /* Close Document & window it supervises AFTER we close all the
  370.     ** above because CDocument::Dispose sets all views and sub-views
  371.     ** to NULL and "itsMovie" is one of these.  CDocument::Dispose
  372.     ** also dumps CDocument::lastTask, the CTask instance variable
  373.     ** used for undoing.  It also disposes of my CMovieFile since
  374.     ** I placed it in CDocument::itsFile when I either called
  375.     ** DoSaveAs with a new Movie or opened an existing Movie file.    */
  376.     
  377.     inherited::Dispose();
  378.  
  379. }    /* Dispose */
  380.  
  381.  
  382.  
  383. // OVERRIDE
  384. void    CQuickTime::UpdateMenus (void)        {
  385.         
  386.         Movie        localMoov;
  387.         
  388.         
  389.     /* Call CDocument::UpdateMenus which enables cmdSaveAs
  390.     ** and, if CDocument::dirty is TRUE, enables cmdSave.
  391.     ** Because I am using the identical Command Numbers in
  392.     ** cmdSaveAsMovie and cmdSaveMovie, respectively, I need
  393.     ** to carefully re-disable some of these commands depending ... */
  394.     
  395.     inherited::UpdateMenus();            // Keep on trucking !!!
  396.         
  397.     if (itsMovie)        {
  398.         
  399.      // gBartender->EnableCmd(cmdCloseMovie);  --  done by CDirector::UpdateMenus
  400.         
  401.         localMoov = itsMovie->GetMovie();
  402.         
  403.         /*
  404.         ** A brand new window is not dirty, so there's nothing to save.
  405.         ** A cut or cleared window IS dirty even though the resultant
  406.         ** NeewMovie is empty with a duration = 0.  I don't know why
  407.         ** you'd wish to save an empty Movie, but it can be loaded.
  408.         **                            ... so ...
  409.         */
  410.         if (localMoov /* && GetMovieDuration(localMoov) > 0 */)        {
  411.          /* Done by CDocument's UpdateMenus if (dirty):
  412.          ** gBartender->EnableCmd(cmdSaveMovie);        */
  413.             gBartender->EnableCmd(cmdSaveAsMovie);
  414.         }
  415.         else    {
  416.             gBartender->DisableCmd(cmdSaveMovie);
  417.             gBartender->DisableCmd(cmdSaveAsMovie);
  418.         }
  419.         
  420.     }    /* itsMovie */
  421.  
  422.     else    {
  423.      /*
  424.      ** Gotta be able to close the darn window.  If itsMovie = NULL,
  425.      ** my CQuickTime::Dispose will NOT call ClearQuickTime.
  426.      **
  427.      ** gBartender->DisableCmd(cmdCloseMovie);
  428.      */
  429.         gBartender->DisableCmd(cmdSaveMovie);
  430.         gBartender->DisableCmd(cmdSaveAsMovie);
  431.     }
  432.  
  433. }    /* UpdateMenus */
  434.  
  435.  
  436.     
  437. // OVERRIDE
  438. void    CQuickTime::DoCommand (long theCommand)        {
  439.         
  440.     
  441.     if (itsMovie)        {
  442.         
  443.         switch (theCommand)        {
  444.         
  445.          /* Standard Command Numbers handled by CDocument::DoCommand(...)
  446.          
  447.             case cmdCloseMovie:
  448.             
  449.                 this->Close(FALSE);            // Calls Dispose.
  450.                 break;
  451.                 
  452.             case cmdSaveMovie:
  453.             
  454.                 SetCursor(*gWatchCursor);
  455.                 DoSave();
  456.                 break;
  457.                 
  458.             case cmdSaveAsMovie:
  459.             
  460.                 DoSaveFileAs();                // Calls DoSaveAs.
  461.                 break;
  462.             
  463.             case cmdRevert:
  464.                 PositionDialog('ALRT', ALRTrevert);
  465.                 if (CautionAlert(ALRTrevert, NULL) == OK) {
  466.                     SetCursor(*gWatchCursor);
  467.                     DoRevert();
  468.                 }
  469.                 break;
  470.                 
  471.             case cmdUndo:
  472.         
  473.                 if (lastTask != NULL)    {
  474.                     if (undone)        lastTask->Redo();
  475.                     else            lastTask->Undo();
  476.  
  477.                     undone = !undone;
  478.                     UpdateUndo();
  479.                 }
  480.                 break;
  481.                 
  482.          */
  483.                 
  484.             default:
  485.             
  486.                 CView::cCurrHelpView = NULL;
  487.                 CView::cLastHelpView = NULL;
  488.                 ;
  489.                 inherited::DoCommand(theCommand);
  490.                 break;
  491.                 
  492.         }    /* end: switch */
  493.         
  494.     }    /* itsMovie */
  495.     
  496.  /*
  497.  ** Do NOT pass up to CDocument::DoCommand if itsMovie = NULL:
  498.  ** else    inherited::DoCommand(theCommand);
  499.  */
  500.  
  501. }    /* DoCommand */
  502.  
  503.  
  504.     
  505. // OVERRIDE
  506. Boolean        CQuickTime::DoSave (void)        {
  507.  
  508.         MovieController        localMC;
  509.         Movie                localMoov;
  510.         CMovieFile            *movieFile    = GetMovieFile();
  511.         TimeValue            currentTime, currentDuration, lengthMovie;
  512.         
  513.     
  514.     if ( movieFile == NULL /* a brand NeewMovie */ )
  515.         return    ( DoSaveFileAs() );
  516.     else    {
  517.         /* we came from DoSaveAs OR we created a file when we opened a Movie */
  518.  
  519.         movieFile->Update();    // Calls FlushVol.
  520.     
  521.         /*
  522.         ** If we came here via DoSaveAs, we called:
  523.         **            dirty = !dirty;
  524.         ** so we need to switch back to maintain constancy.
  525.         ** If we came here via selecting the "Save Movie"
  526.         ** item under the File MENU, the document was dirty
  527.         ** to begin with, so we set dirty = false:
  528.         */
  529.         dirty = !dirty;
  530.         
  531.         justSaved = true;        // For my special CView::DispatchCursor.
  532.  
  533.         // For reverting:
  534.         if (savedMovie != nil && GetMovieDuration(savedMovie) > 0)    {
  535.             DisposeMovie(savedMovie);
  536.             FailOSErr( GetMoviesError() );
  537.         }
  538.         localMC = itsMovie->GetController();
  539.         localMoov = itsMovie->GetMovie();
  540.         lengthMovie = GetMovieDuration(localMoov);
  541.         FailOSErr( GetMoviesError() );
  542.         if (lengthMovie > 0)    {
  543.             GetMovieSelection(localMoov, ¤tTime, ¤tDuration);
  544.             FailOSErr( GetMoviesError() );
  545.             SetMovieSelection(localMoov, 0 /* beginning */, lengthMovie);
  546.             FailOSErr( GetMoviesError() );
  547.             localMoov = MCCopy(localMC);
  548.             FailOSErr( GetMoviesError() );
  549.             SetMovieSelection(localMoov, currentTime, currentDuration);
  550.             FailOSErr( GetMoviesError() );
  551.         }
  552.         else    localMoov = NewMovie(newMovieActive);
  553.         savedMovie = localMoov;
  554.                 
  555.         return    (TRUE);
  556.         
  557.     }    /* else */
  558.         
  559. }    /* DoSave */
  560.  
  561.  
  562.  
  563. // OVERRIDE
  564. Boolean        CQuickTime::DoSaveAs (SFReply *macSFReply)        {
  565.  
  566.         CMovieFile            *movieFile    = GetMovieFile();
  567.         StandardFileReply    newReply;
  568.         short                fileRefNum;
  569.         Movie                newMoov        = itsMovie->GetMovie();
  570.         WindowPtr            localWindow    = itsWindow->GetMacPort();
  571.         
  572.  
  573.     if (movieFile != NULL /* Did NOT come from DoSave */ )
  574.         movieFile->Dispose();                    // Calls Close().
  575.     
  576.     ConvertOldToNew(macSFReply, &newReply);        // Calls FSMakeFSSpec
  577.     ;
  578.     NewFile();
  579.     
  580.     movieFile = GetMovieFile();
  581.     movieFile->SpecifyFSSpec(&newReply.sfFile);
  582.     movieFile->CreateNew(gSignature, gApplication->sfFileTypes[0]);
  583.  
  584.     movieFile->Open(fsRdWrPerm);
  585.     fileRefNum = itsMovie->GetMoovRefNum();
  586.  
  587.     SetMovieActive(newMoov, true);
  588.     FailOSErr( GetMoviesError() );
  589.  
  590.     SetMovieGWorld(newMoov, (CGrafPtr) localWindow, nil);
  591.     FailOSErr( GetMoviesError() );
  592.     
  593.     MakeFilePreview(fileRefNum, 0);
  594.     FailOSErr( GetMoviesError() );
  595.  
  596.      // itsMovie->moov = newMoov;  --  knew this coming in.
  597.  
  598.     itsWindow->SetTitle(macSFReply->fName);
  599.  
  600.     dirty = !dirty;            // See comments at end of DoSave().
  601.     
  602.     return ( DoSave() );
  603.     
  604. }    /* DoSaveAs */
  605.  
  606.  
  607.  
  608. /*
  609. ** OVERRIDE
  610. **
  611. **        just to blink on/off the prompt string item when the Movie is empty
  612. ** 
  613. ** CQuickTime::PickFileName
  614. */
  615.  
  616. static pascal short        MyDlgHook (short theItem, DialogPtr theDialog)        {
  617.  
  618.         short        promptItem = 3, itemType;
  619.         Rect        promptBox;
  620.         Handle        item;
  621.         long        finalTicks;
  622.         
  623.         
  624.     if (theItem == sfHookNullEvent /* = 100 */)        {
  625.         GetDItem(theDialog, promptItem, &itemType, &item, &promptBox);
  626.         InvertRect(&promptBox);
  627.         Delay(30, &finalTicks);
  628.     }
  629.     
  630.     return    (theItem);
  631.     
  632. }    /* MyDlgHook */
  633.  
  634.  
  635.  
  636. // OVERRIDE
  637. void    CQuickTime::PickFileName (SFReply *macSFReply)        {
  638.     
  639.         Point            corner;                /* Top left corner of dialog box */
  640.         Str255            origName,            /* Default name for file */
  641.                         prompt,                /* Prompt strings: */
  642.                         emptyMoviePrompt = "\pWARNING: Movie is EMPTY !!!",
  643.                         fullMoviePrompt     = "\pSave Movie File as:";
  644.         Movie            localMoov         = itsMovie->GetMovie();
  645.         Boolean            movieIsEmpty     = GetMovieDuration(localMoov) == 0,
  646.                         wasLocked;
  647.         ProcPtr            filterProc = NULL,
  648.                         dlgHook       = (movieIsEmpty) ? (ProcPtr) &MyDlgHook : NULL;
  649.  
  650.  
  651.     wasLocked = Lock(TRUE);
  652.     
  653.     FindDlogPosition('DLOG', putDlgID, &corner);    // Center Dialog.
  654.     
  655.     GetName(origName);
  656.     
  657.     if (movieIsEmpty)    {
  658.             CopyPString(emptyMoviePrompt, prompt);
  659.             SysBeep(10);
  660.     }
  661.     else    CopyPString(fullMoviePrompt, prompt);
  662.     
  663.     SFPPutFile(corner, prompt, origName, dlgHook, macSFReply, putDlgID, filterProc);
  664.  
  665.     Lock(wasLocked);
  666.     
  667. }    /* PickFileName */
  668.  
  669.  
  670.  
  671. /*
  672. ** OVERRIDE
  673. **
  674. **        just to implement CMD-key equivalents for responses
  675. ** 
  676. ** CQuickTime::ConfirmClose
  677. */
  678.  
  679. static pascal Boolean    MyResponseFilter(DialogPtr theDialog,
  680.                                          EventRecord *theEvent,
  681.                                          short *itemHit)    {
  682.         
  683.         #define kCR        13
  684.         Boolean            cmdKeyDown        = (theEvent->modifiers & cmdKey) > 0,
  685.                         processNormally    = false,
  686.                         interceptEvent    = true;
  687.         char            theKey            = theEvent->message & charCodeMask;
  688.         short            itemType;
  689.         Rect            itemBox;
  690.         Handle            item;
  691.         long            finalTicks;
  692.         
  693.                                          
  694.     if (theEvent->what != keyDown)        return (processNormally);
  695.         
  696.     if (theKey == kEnterKey || theKey == kCR)    {
  697.         GetDItem(theDialog, *itemHit = answerYES, &itemType, &item, &itemBox);
  698.         HiliteControl((ControlHandle)item, inButton);
  699.         Delay(20, &finalTicks);
  700.     }
  701.     
  702.     else if (cmdKeyDown)    {
  703.         if (theKey == 'y' || theKey == 'Y')        {
  704.             GetDItem(theDialog, *itemHit = answerYES, &itemType, &item, &itemBox);
  705.             HiliteControl((ControlHandle)item, inButton);
  706.             Delay(20, &finalTicks);
  707.         }
  708.         
  709.         else if (theKey == 'n' || theKey == 'N')        {
  710.             GetDItem(theDialog, *itemHit = answerNO, &itemType, &item, &itemBox);
  711.             HiliteControl((ControlHandle)item, inButton);
  712.             Delay(20, &finalTicks);
  713.         }
  714.         
  715.         else if (theKey == '.')        {
  716.             GetDItem(theDialog, *itemHit = answerCANCEL, &itemType, &item, &itemBox);
  717.             HiliteControl((ControlHandle)item, inButton);
  718.             Delay(20, &finalTicks);
  719.         }
  720.         
  721.         else
  722.             return (processNormally);
  723.     }    /* CMD-key is down */
  724.         
  725.     return (interceptEvent);
  726.     
  727. }    /* MyResponseFilter */
  728.  
  729.  
  730.  
  731. // OVERRIDE
  732. Boolean        CQuickTime::ConfirmClose (Boolean quitting)        {
  733.  
  734.         Boolean        okToClose = TRUE;
  735.         Str255        docName, status;
  736.         short        response;
  737.  
  738.  
  739.     if (dirty)        {    /* If Document has changed ... */
  740.     
  741.         if (itsWindow != NULL)        itsWindow->Update();
  742.             
  743.         GetName(docName);
  744.         GetIndString(status,
  745.                      STRcommon,
  746.                      (quitting) ? strQUITTING : strCLOSING);
  747.         /* Ask user if s/he wants to save the changes: */
  748.         ParamText(docName, status, NULL, NULL);
  749.         PositionDialog('ALRT', ALRTsaveChanges);
  750.         InitCursor();
  751.         response = Alert(ALRTsaveChanges, (ProcPtr) &MyResponseFilter);
  752.         
  753.         if (response == answerYES)    {
  754.             SetCursor(*gWatchCursor);
  755.             okToClose = DoSave();        /* Save Document before closing it.    */
  756.         }
  757.         else if (response == answerCANCEL) {
  758.             okToClose = FALSE;            /* Abort the close. */
  759.         }
  760.      /* else if (response == answerNO) we don't need to do
  761.      ** anything more because "okToClose" was preset to TRUE. */
  762.      
  763.     }    /* if dirty */
  764.     
  765.     return(okToClose);
  766.     
  767. }    /* ConfirmClose */
  768.  
  769.  
  770.  
  771. void    CQuickTime::NewFile (void)    {
  772.  
  773.         CMovieFile            *movieFile = NULL;
  774.  
  775.  
  776.     movieFile = new (CMovieFile);
  777.     movieFile->IMovieFile();
  778.     SetMovieFile(movieFile);        // itsFile = movieFile, etc.
  779.     
  780. }    /* NewFile */
  781.  
  782.  
  783.  
  784. void    CQuickTime::OpenMoovFile (SFReply *macSFReply)        {
  785. /* Get a movie file and a movie out of the good SFReply: */
  786.  
  787.         StandardFileReply    newReply;
  788.         Movie                localMoov;
  789.         OSErr                err;
  790.         short                movieFileRefNum,
  791.                             rsrcID = 0        /* Get first 'moov' found */;
  792.         Boolean                wasChanged;
  793.         Str255                moovResName;
  794.         CMovieFile            *movieFile;
  795.  
  796.     
  797.     ConvertOldToNew(macSFReply, &newReply);
  798.     
  799.     NewFile();
  800.     movieFile = GetMovieFile();
  801.     movieFile->SpecifyFSSpec(&newReply.sfFile);
  802.     
  803.     movieFile->Open(fsRdWrPerm);
  804.     movieFileRefNum = movieFile->refNum;        // CResFile::refNum
  805.     err = NewMovieFromFile(&localMoov, movieFileRefNum, &rsrcID, moovResName,
  806.                            newMovieActive, &wasChanged);
  807.     if (err == noErr)    {
  808.         itsMovie->moov = localMoov;
  809.         movieFile->resID = rsrcID;
  810.     }
  811.     else    {
  812.         movieFile->Dispose();                    // Close & Dispose
  813.         FailOSErr(err);
  814.     }
  815.         
  816.     itsWindow->SetTitle(newReply.sfFile.name);
  817.     
  818. }    /* OpenMoovFile */
  819.  
  820.  
  821.  
  822. void    CQuickTime::SetMovieFile (CMovieFile *movieFile)    {
  823.  
  824.  
  825.     movieFile->theMovie = itsMovie;
  826.     itsFile = movieFile;
  827.  
  828. }    /* SetMovieFile */
  829.  
  830.  
  831.  
  832. CMovieFile        *CQuickTime::GetMovieFile (void)    {
  833.  
  834.  
  835.     return    ( (CMovieFile*)itsFile );
  836.     
  837. }    /* GetMovieFile */
  838.  
  839.  
  840.  
  841. void    CQuickTime::DoRevert (void)        {
  842. /* Close current Movie file without writing-to-disk
  843. ** and read in the last saved version of the Movie:    */
  844.  
  845.         CMovieFile            *movieFile    = GetMovieFile();
  846.         CMovieEditTask        *editTask;
  847.         MovieController        activeMC;
  848.         Movie                savedMoov    = savedMovie, activeMoov;
  849.         TimeValue            atStart        = 0,
  850.                             noDuration    = 0, movieLength;
  851.         GrafPtr                currentPort    = itsMainPane->GetMacPort();
  852.  
  853.  
  854.     ASSERT( /*
  855.             ** CDocument::UpdateMenus won't enable the
  856.             ** Revert MENU item if CDocument::itsFile = NULL:
  857.             **
  858.             ** movieFile != NULL && 
  859.             */
  860.             movieFile->IsOpen()
  861.           );
  862.  
  863.     itsWindow->HideSuspend();
  864.     ;
  865.     itsMovie->MakeMovieEditTask(cmdRevert);
  866.  
  867.     activeMC = itsMovie->GetController();
  868.     activeMoov = itsMovie->GetMovie();
  869.  
  870.     movieLength = GetMovieDuration(activeMoov);
  871.     if (movieLength > 0)    {
  872.         SetMovieSelection(activeMoov, 0, movieLength);
  873.         FailOSErr( GetMoviesError() );
  874.         itsMovie->ClearSelection();
  875.     }
  876.     if (savedMoov != NULL && GetMovieDuration(savedMoov) > 0)    {
  877.         MCPaste(activeMC, savedMoov);
  878.         FailOSErr( GetMoviesError() );
  879.         SetMovieSelection(activeMoov, atStart, noDuration);        // Zip.
  880.         FailOSErr( GetMoviesError() );
  881.         GoToBeginningOfMovie(activeMoov);
  882.         FailOSErr( GetMoviesError() );
  883.     }
  884.         
  885.     Notify(itsMovie->lastMovieEditTask);
  886.     itsMovie->lastMovieEditTask->Do();
  887.     
  888.     dirty = false;
  889.     ;
  890.     itsWindow->ShowResume();
  891.  
  892. }    /* DoRevert */
  893.  
  894.  
  895.  
  896. void    CMovie::IMovie (CView *anEnclosure, CBureaucrat *aSupervisor)    {
  897.         
  898.         
  899.     inherited::IPane(
  900.                         anEnclosure, aSupervisor,
  901.                         0, 0, 0, 0,            /* Call FitToEnclosure next */
  902.                         sizELASTIC, sizELASTIC
  903.                     );
  904.     FitToEnclosure(true, true);
  905.     moov = NULL;
  906.     mc = NULL;
  907.     lastMovieEditTask = NULL;
  908.     
  909.     /* Upon start-up, IApplication sets "gGopher" to my application.
  910.     ** CBureaucrat::BecomeGopher below resets "gGopher" to this Movie
  911.     ** view.  When CSitchboard::DispatchEvent responds to a click in
  912.     ** the MenuBar or to a CMD-keypress, eventually the TCL will call
  913.     ** gGopher->DoCommand(...).  Therefore, CMovie::DoCommand is called.
  914.     **
  915.     ** CBureaucrat's BecomeGopher will then call:
  916.     **        BroadcastChange( bureaucratIsGopher, 0);
  917.     ** which then calls:
  918.     **        itsSupervisor->ProviderChanged(this, reason, info);
  919.     ** where "this" = THIS CMovie view because it was the CBureaucrat
  920.     ** that was sent the ORIGINAL message = BecomeGopher.  Since
  921.     ** "itsSupervisor" is my document = CQuickTime,
  922.     **        CDirector::ProviderChanged
  923.     ** is the contraption that is really called because a CDocument
  924.     ** is a CDirector.
  925.     **
  926.     ** CDirector's ProviderChanged tests to see if the "this" CMovie
  927.     ** is active and it's NOT because the enclosing window has not YET
  928.     ** been activated.  As a direct result, "CDirector::itsGopher"
  929.     ** is NOT changed to my CMovie view.  I have to do that when I
  930.     ** return to either IQuickTime or INewQuickTime.
  931.     **
  932.     **                    If I do NOT, look out !!!
  933.     **
  934.     ** Okay ... what have we got so far???  "gGopher" is my CMovie view.
  935.     ** Before I called IMovie within either IQuickTime or INewQuickTime,
  936.     ** I called IDocument which called IDirector.  IDirector calls:
  937.     **                    itsGopher = this;
  938.     ** where "this" is my CQuickTime document.  Folks, we've got a mismatch.
  939.     **
  940.     ** The purpose of "itsGopher" is to "remember" which bureaucrat is
  941.     ** supposed to become the gopher when the director's window is made
  942.     ** active.  After I'm completely finished with either IQuickTime or
  943.     ** INewQuickTime, CWindow::Select is called within DisplayQuickTime
  944.     ** to finally activate the window.  CDirector::ActivateWind gets
  945.     ** called to set all views and sub-views active.  The latter method
  946.     ** calls CDirector::Activate which, in turn, calls:
  947.     **        itsGopher->BecomeGopher(TRUE);
  948.     **
  949.     **                            WHOOAH !!!!
  950.     **
  951.     ** If we did NOT change "itsGopher" to match "gGopher", then sending
  952.     ** BecomeGopher to "itsGopher" changes "gGopher" back to "itsGopher"
  953.     ** which is my CQuickTime document because that's what "itsGopher"
  954.     ** becomes upon window activation without my intercession (see above
  955.     ** comments about IDirector).  In short, the TCL forces a match.     */
  956.  
  957.     BecomeGopher(true);
  958.     SetWantsClicks(true);        /* IView sets both to false. */
  959.     SetCanBeGopher(true);
  960.  
  961. }    /* IMovie */
  962.  
  963.  
  964.  
  965. void    CMovie::NeewMovie (void)    {
  966. /* Note that we do NOT call CQuickTime's MakeMovieFile
  967. ** so that CQuickTime::DoSave can jump over to DoSaveAs
  968. ** to create a new FSSpec.                                */
  969.  
  970.         Movie            localMoov;
  971.         WindowPtr        localWindow    = GetMacPort();
  972.                 
  973.         
  974.     Prepare();            // Set the blasted Port !!!
  975.     
  976.     localMoov = NewMovie(newMovieActive);        // duration = 0.
  977.     moov = localMoov;
  978.     
  979.     SetMovieGWorld(localMoov, (CGrafPtr) localWindow, nil);
  980.     FailOSErr( GetMoviesError() );
  981.     
  982.     NeewController();
  983.  
  984. }    /* NeewMovie */
  985.  
  986.  
  987.  
  988. static void        FloatingWindow_Update (CWindow *theWindow)        {
  989. /* gDesktop->UpdateWindows() called by CMovie::OpenMovie below
  990. ** addresses ONLY the CList = CDesktop->itsWindows, NOT the
  991. ** CList = ((CFWDesktop*) gDesktop)->itsFloats.  So ...           */
  992.  
  993.         WindowPeek        macWindow;
  994.             
  995.             
  996.     macWindow = (WindowPeek) theWindow->GetMacPort();
  997.     if ( !EmptyRgn(macWindow->updateRgn) )        theWindow->Update();
  998.  
  999. }    /* FloatingWindow_Update */
  1000.  
  1001.  
  1002.  
  1003. void    CMovie::OpenMovie (SFReply *macSFReply)        {
  1004.  
  1005.         CQuickTime            *myDoc        = (CQuickTime*) GetSupervisor();
  1006.         CWindow                *theWindow    = GetWindow();
  1007.         WindowPtr            localWindow    = GetMacPort();
  1008.         MovieController        localMC;
  1009.         Movie                localMoov;
  1010.         TimeValue            atBeginning    = 0, currentTime,
  1011.                             currentDuration, lengthMovie;
  1012.         short                saveProcID;
  1013.  
  1014.  
  1015.     /* We just selected a Movie.  The special Movie version of the SFGetFile
  1016.     ** Dialog has just disappeared ... so Update what's there before we play
  1017.     ** the next Movie.  Note that if we had NOT selected a Movie by clicking
  1018.     ** the Dialog's <Cancel> Button, CApplication::DoCommand will NOT call
  1019.     ** CStarterApp::OpenDocument to access OpenMovie.  However, we WILL
  1020.     ** eventually update all windows the next time through the Event Loop.
  1021.     ** So we only force an immediate update IF we do select a Movie.        */
  1022.     
  1023.     gDesktop->UpdateWindows();
  1024.     ((CMovieDesktop*) gDesktop)->itsFloats->
  1025.                                     DoForEach((EachFunc) FloatingWindow_Update);
  1026.     
  1027.     myDoc->OpenMoovFile(macSFReply);
  1028.     localMoov = GetMovie();
  1029.         
  1030.     Prepare();
  1031.     
  1032.     SetMovieGWorld(localMoov, (CGrafPtr) localWindow, nil);
  1033.     FailOSErr( GetMoviesError() );
  1034.     SetMovieActive(localMoov, true);
  1035.     FailOSErr( GetMoviesError() );
  1036.     
  1037.     OpenController();
  1038.  
  1039.     localMC = GetController();
  1040.     lengthMovie = GetMovieDuration(localMoov);
  1041.     FailOSErr( GetMoviesError() );
  1042.     if (lengthMovie > 0)    {
  1043.         GetMovieSelection(localMoov, ¤tTime, ¤tDuration);
  1044.         FailOSErr( GetMoviesError() );
  1045.         SetMovieSelection(localMoov, atBeginning, lengthMovie);
  1046.         FailOSErr( GetMoviesError() );
  1047.         localMoov = MCCopy(localMC);
  1048.         FailOSErr( GetMoviesError() );
  1049.         SetMovieSelection(localMoov, currentTime, currentDuration);
  1050.         FailOSErr( GetMoviesError() );
  1051.     }
  1052.     else    localMoov = NewMovie(newMovieActive);
  1053.     myDoc->savedMovie = localMoov;
  1054.  
  1055.     PrepCombinedMovieAndController();
  1056.     
  1057.     /* PrepCombinedMovieAndController will re-size the
  1058.     ** window to accomodate the Movie.  Therefore, we
  1059.     ** must wait to center the window until last:       */
  1060.     saveProcID = theWindow->procID;
  1061.     theWindow->SetModal(false);
  1062.     theWindow->procID = 0;
  1063.     gDecorator->CenterWindow(theWindow);
  1064.     theWindow->procID = saveProcID;
  1065.     
  1066.     gDecorator->wCount++;
  1067.                     
  1068. }    /* OpenMovie */
  1069.  
  1070.  
  1071.  
  1072. Movie    CMovie::GetMovie (void)        {
  1073.  
  1074.  
  1075.     return    (moov);
  1076.     
  1077. }    /* GetMovie */
  1078.  
  1079.  
  1080.  
  1081. void    CMovie::NeewController (void)    {
  1082.  
  1083.         Boolean                savedAlloc;
  1084.         Movie                localMoov = GetMovie();
  1085.         MovieController        localMC;
  1086.         LongRect            frameRect = frame;
  1087.         Rect                windRect;
  1088.         
  1089.         
  1090.     Prepare();
  1091.  
  1092.     FrameToWindR(&frameRect, &windRect);
  1093.      savedAlloc = SetAllocation(kAllocCanFail);
  1094.     localMC = NewMovieController(localMoov, &windRect,
  1095.                                  mcTopLeftMovie
  1096.                               /* + mcWithBadge    [see ShowBadge below] */);
  1097.     SetAllocation(savedAlloc);
  1098.     FailOSErr( GetMoviesError() );
  1099.     mc = localMC;
  1100.  
  1101.     SetUpFilter(true);
  1102.     ShowBadge(true);
  1103.     EnableKeys(true);
  1104.     MCEnableEditing(localMC, true);
  1105.     FailOSErr( GetMoviesError() );
  1106.     
  1107.     PrepCombinedMovieAndController();
  1108.     
  1109. }    /* NeewController */
  1110.  
  1111.  
  1112.  
  1113. void    CMovie::OpenController (void)    {
  1114.  
  1115.         Movie                    localMoov     = GetMovie();
  1116.         MovieController            localMC;
  1117.         WindowPtr                localWindow   = GetMacPort();
  1118.         Point                    topLeftCorner = {0, 0};
  1119.         ComponentDescription    cd;
  1120.         Component                c, searchAll  = nil;
  1121.         
  1122.         
  1123.     cd.componentType = 'play';
  1124.     cd.componentSubType = 0;                /* none */
  1125.     cd.componentManufacturer = 'appl';
  1126.     cd.componentFlags = 0;                    /* no Register message */
  1127.     cd.componentFlagsMask = 0;                /* ... because componentFlags = 0 */
  1128.     
  1129.     c = FindNextComponent(searchAll, &cd);
  1130.     FailNIL(c);
  1131.     localMC = OpenComponent(c);
  1132.     FailNIL(localMC);
  1133.     mc = localMC;                            /* Stuff into instance variable. */
  1134.     MCSetControllerAttached(localMC, true);
  1135.     FailOSErr( GetMoviesError() );
  1136.     MCSetMovie(localMC, localMoov, localWindow, topLeftCorner);
  1137.     FailOSErr( GetMoviesError() );
  1138.     MCSetVisible(localMC, true);
  1139.     FailOSErr( GetMoviesError() );
  1140.     
  1141.     MCEnableEditing(localMC, true);
  1142.     FailOSErr( GetMoviesError() );
  1143.  
  1144.     SetUpFilter(true);
  1145.     ShowBadge(true);
  1146.     EnableKeys(true);
  1147.     
  1148. }    /* OpenController */
  1149.  
  1150.  
  1151.  
  1152. MovieController        CMovie::GetController (void)    {
  1153.  
  1154.  
  1155.     return    (mc);
  1156.     
  1157. }    /* GetController */
  1158.  
  1159.  
  1160.  
  1161. short    CMovie::GetMoovRefNum (void)        {
  1162.  
  1163.         CQuickTime        *myDoc       = (CQuickTime*) GetSupervisor();
  1164.         CMovieFile        *movieFile = myDoc->GetMovieFile();
  1165.         
  1166.         
  1167.     if (movieFile)        return    (movieFile->refNum);
  1168.     else                return    (noMoovFile);
  1169.     
  1170. }    /* GetMoovRefNum */
  1171.  
  1172.  
  1173.  
  1174. void    CMovie::PrepCombinedMovieAndController (void)    {
  1175.  
  1176.         Movie                localMoov    = GetMovie();
  1177.         MovieController        localMC        = GetController();
  1178.         CWindow                *theWindow    = GetWindow();
  1179.         OSErr                err;
  1180.         Rect                moovBox, controllerBox, both, minMaxWindowBounds;
  1181.  
  1182.         
  1183.     GetMovieBox(localMoov, &moovBox);
  1184.     FailOSErr( GetMoviesError() );
  1185.     // Movie box may come with negative coordinates, so ...
  1186.     OffsetRect(&moovBox, -moovBox.left, -moovBox.top);
  1187.     SetMovieBox(localMoov, &moovBox);
  1188.     FailOSErr( GetMoviesError() );
  1189.     FailOSErr( MCMovieChanged(localMC, localMoov) );
  1190.     
  1191.     /* CQuickTime::DisplayQuickTime calls CWindow::Select which
  1192.     ** results in an update event which, in turn, results in
  1193.     ** CMovie::Draw being called.  The latter calls UpdateMovie:
  1194.     UpdateMovie(localMoov);
  1195.     FailOSErr( GetMoviesError() );                                */
  1196.             
  1197.     /* Incorporate a SizeBox as part of the Controller and
  1198.     ** set limits on window growth.  The latter is directly
  1199.     ** analogous to setting CWindow::sizeRect to the same limits: */
  1200.     minMaxWindowBounds = theWindow->sizeRect;
  1201.     MCDoAction(localMC, mcActionSetGrowBoxBounds, &minMaxWindowBounds);
  1202.  
  1203.     /* Next get the union of the Controller & Movie boxes in order to size the
  1204.     ** window.  You may not have noticed, but the window is NOT growable as far
  1205.     ** as the Window Manager is concerned.  When we call MCDoAction below, what
  1206.     ** we are really doing is sending a mcActionControllerSizeChanged action
  1207.     ** message to my MCFilter.  This MCFilter re-sizes the window.
  1208.     **
  1209.     **                                Neat, HUH !!!
  1210.     **
  1211.     ** By the way, with QuickTime, version 1.0, to send the above action message,
  1212.     ** all I needed to do was to call _MCSetControllerBoundsRect.  NO MO!!!          */
  1213.     
  1214.     err = MCGetControllerBoundsRect(localMC, &controllerBox);
  1215.     FailOSErr(err);
  1216.     OffsetRect(&controllerBox, -controllerBox.left, -controllerBox.top);
  1217.     UnionRect(&moovBox, &controllerBox, &both);
  1218.  
  1219.     /* Send mcActionControllerSizeChanged to my MCFilter
  1220.     ** so my Window can be re-sized proportionally:        */
  1221.     err = MCDoAction(localMC, mcActionControllerSizeChanged, &both);
  1222.     if (err == noErr ||
  1223.         err == controllerBoundsNotExact /* Controller Manager made it exact */)
  1224.             err = MCMovieChanged(localMC, localMoov);
  1225.     FailOSErr(err);
  1226.  
  1227. }    /* PrepCombinedMovieAndController */
  1228.  
  1229.  
  1230.  
  1231. void    CMovie::PlayMovie (void)    {
  1232.  
  1233.         Movie                activeMoov      = GetMovie();
  1234.         MovieController        activeMC      = GetController();
  1235.         OSErr                err;
  1236.         GrafPtr                currentPort      = GetMacPort();
  1237.         GDHandle            currentDevice = nil;
  1238.         TimeValue            startTime      = 0,
  1239.                             currentTime,
  1240.                             noDuration      = 0;
  1241.         Fixed                rate          = 0;
  1242.         long                maxSleep;
  1243.  
  1244.  
  1245.     HideCursor();                    /* TOO MUCH fluttering !!! */
  1246.  
  1247.     // Play the movie in the window:
  1248.     SetMovieGWorld(activeMoov, (CGrafPtr) currentPort, currentDevice);
  1249.     FailOSErr( GetMoviesError() );                // NEVER returns if an error !!!
  1250.     
  1251.     // Now we're ready to play the movie:
  1252.     GoToBeginningOfMovie(activeMoov);
  1253.     FailOSErr( GetMoviesError() );
  1254.  
  1255.     /* StartMovie does these:
  1256.     PrerollMovie(activeMoov, startTime, rate);    // Get the movie ready to play.
  1257.     FailOSErr( GetMoviesError() );
  1258.  
  1259.     SetMovieActive(activeMoov, true);
  1260.     FailOSErr( GetMoviesError() );            */
  1261.  
  1262.     StartMovie(activeMoov);                        // Start the movie.
  1263.     FailOSErr( GetMoviesError() );
  1264.  
  1265.     /* Play the movie until done or the mouse button has been pressed */
  1266.     while ( !IsMovieDone(activeMoov) && !Button() )
  1267.         Dawdle(&maxSleep);
  1268.     
  1269.     if (IsMovieDone(activeMoov))        {
  1270.         GoToBeginningOfMovie(activeMoov);        // ... otherwise we stay at end.
  1271.         FailOSErr( GetMoviesError() );
  1272.         /* ... otherwise we play it AGAIN ????? */
  1273.         StopMovie(activeMoov);
  1274.         FailOSErr( GetMoviesError() );
  1275.         /* Redraw so Controller Bar's Thumb appears at beginning: */
  1276.         Dawdle(&maxSleep);
  1277.     }
  1278.     
  1279.     // Set selection to zero, otherwise WHOLE Movie is selected:
  1280.     currentTime = GetMovieTime(activeMoov, nil /* don't need TimeRecord */);
  1281.     FailOSErr( GetMoviesError() );
  1282.     SetMovieSelection(activeMoov, currentTime, noDuration);
  1283.     FailOSErr( GetMoviesError() );
  1284.     Activate();                                    // So new selection shows.
  1285.         
  1286.     ShowCursor();
  1287.  
  1288. }    /* PlayMovie */
  1289.  
  1290.  
  1291.  
  1292. void    CMovie::DisposMoovie (void)    {
  1293.  
  1294.         Movie    localMoov = GetMovie();
  1295.  
  1296.  
  1297.     if (localMoov)    {
  1298.         /* MCCut & MCClear effectively void the Movie by setting
  1299.         ** its duration = 0.  In short, it's really gone !!!    */
  1300.         if (GetMovieDuration(localMoov) != 0)    {
  1301.             DisposeMovie(localMoov);
  1302.             FailOSErr( GetMoviesError() );
  1303.         }
  1304.         moov = nil;                                        // Mark as gone !!!
  1305.     }
  1306.  
  1307. }    /* DisposMoovie */
  1308.  
  1309.  
  1310.  
  1311. void    CMovie::DisposController (void)    {
  1312.  
  1313.         MovieController        localMC = GetController();
  1314.         
  1315.         
  1316.     if (localMC != NULL)    {
  1317.         DisposeMovieController(localMC);
  1318.         FailOSErr( GetMoviesError() );
  1319.         mc = nil;                                        // See ya around !!!
  1320.     }
  1321.     
  1322. }    /* DisposController */
  1323.  
  1324.  
  1325.  
  1326. static pascal Boolean        MCFilter (MovieController mcPlay, short *Action,
  1327.                                       long params)        {
  1328. /* purpose: This function gets called whenever the controller is about
  1329. **            to perform an action.  Here we use it to resize the window
  1330. **            in response to an Editing action, e.g, cutting and pasting.    */
  1331.     
  1332.         Rect            moovBox, controllerBox, newWindowPortRect;
  1333.         Movie            localMoov;
  1334.         TimeRecord        currentTime;
  1335.         TimeValue        now;
  1336.         OSErr            err;
  1337.         CGrafPtr        mcPort;
  1338.         CWindow            *mcWind;
  1339.         CMovie            *theMoviePane;
  1340.  
  1341.     // Retrieve some common parms:
  1342.     
  1343.     mcPort = MCGetControllerPort(mcPlay);
  1344.     if (mcPort == nil)        return;            // Is this possible ???
  1345.     
  1346.     localMoov = MCGetMovie(mcPlay);
  1347.     if (GetMoviesError() != noErr)    {
  1348.         SysBeep(10);
  1349.         return;
  1350.     }
  1351.     
  1352.     mcWind = (CWindow*) GetWRefCon((GrafPtr) mcPort);
  1353.  
  1354.  // Because we will be drawing into the window directly with action = mcActionKey:
  1355.     mcWind->ForceNextPrepare();
  1356.     theMoviePane = (CMovie*) gGopher;
  1357.     
  1358.     switch (*Action)    {
  1359.     
  1360.         case mcActionControllerSizeChanged:
  1361.  
  1362.             /* Controller rect includes BOTH the Controller Bar
  1363.             ** AND the Movie (if one exists):                    */
  1364.             
  1365.             err = MCGetControllerBoundsRect(mcPlay, &controllerBox);
  1366.             if (err != noErr)    {
  1367.                 SysBeep(10);
  1368.                 break;
  1369.             }
  1370.             
  1371.             GetMovieBox(localMoov, &moovBox);
  1372.             if (GetMoviesError() != noErr)    {
  1373.                 SysBeep(10);
  1374.                 break;
  1375.             }
  1376.             
  1377.             /* Screwy things happen when we paste a Movie into a Movie window
  1378.             ** wherein the Controller Bar is NOT showing, that is, when the
  1379.             ** Badge IS showing.  Ditto for cutting a Movie which stands to
  1380.             ** reason because before we call MCPaste we call ClearSelection
  1381.             ** which calls MCClear.  MCClear AND its companion, MCCut,
  1382.             ** therefore, appear to hold the common denominator.
  1383.             **
  1384.             ** I do NOT know what the real problem is, but my solution is to
  1385.             ** make the Controller Bar always visible after a cut or clear.      */
  1386.             
  1387.             if (MCGetVisible(mcPlay) == 0)    {            // controller is invisible.
  1388.                 if ( EmptyRect(&moovBox) /* just called MCCut or MCClear */ )    {
  1389.                     /* empty Movie has a rect = {1,1,1,1} */
  1390.                     MCSetVisible(mcPlay, true);
  1391.                     newWindowPortRect = controllerBox;
  1392.                 }
  1393.                 else    {
  1394.                     /* We just clicked in the Movie with the <Option>
  1395.                     ** key pressed to make the Badge appear:          */
  1396.                     newWindowPortRect = moovBox;
  1397.                 }
  1398.             }
  1399.  
  1400.             else /* Controller is visible */    newWindowPortRect = controllerBox;
  1401.  
  1402.             mcWind->ChangeSize(newWindowPortRect.right  - newWindowPortRect.left,
  1403.                                newWindowPortRect.bottom - newWindowPortRect.top);
  1404.             
  1405.          /*
  1406.          ** With this here and the <Option> key pressed, Badge
  1407.          ** shows and then IMMEDIATELY disappears ?????
  1408.             MCMovieChanged(mcPlay, localMoov);
  1409.          */
  1410.          
  1411.             return (FALSE);            // This action does not handle events.
  1412.  
  1413.             break;    /* mcActionControllerSizeChanged */
  1414.  
  1415.  
  1416.         case mcActionKey:
  1417.             // params = a pointer to the EventRecord:
  1418.         
  1419.             if (GetMovieDuration(localMoov) > 0)    {
  1420.                 if ( KeyIsDown(KeyLeftCursor) || KeyIsDown(KeyDownCursor) )        {
  1421.                     theMoviePane->Prepare();
  1422.                     while ((KeyIsDown(KeyLeftCursor) || KeyIsDown(KeyDownCursor)) &&
  1423.                            GetMovieTime (localMoov, ¤tTime) > 0)    {
  1424.                         MCDoAction(mcPlay, mcActionStep, (void*) ((Fixed)-1));
  1425.                         MCIdle(mcPlay);
  1426.                     }
  1427.                 }
  1428.                 
  1429.                 else if ( KeyIsDown(KeyRightCursor) || KeyIsDown(KeyUpCursor) )        {
  1430.                     theMoviePane->Prepare();
  1431.                     while ((KeyIsDown(KeyRightCursor) || KeyIsDown(KeyUpCursor)) &&
  1432.                            !IsMovieDone(localMoov))    {
  1433.                         MCDoAction(mcPlay, mcActionStep, (void*) ((Fixed)1));
  1434.                         MCIdle(mcPlay);
  1435.                     }
  1436.                 }
  1437.             }    /* duration > 0 */
  1438.             
  1439.             return (TRUE);
  1440.             
  1441.             break;    /* mcActionKey */
  1442.             
  1443.             
  1444.         default:
  1445.             return (FALSE);            // Pass it on.
  1446.  
  1447.     }    /* end: switch */
  1448.  
  1449. }    /* MCFilter */
  1450.  
  1451.  
  1452.  
  1453. ComponentResult        CMovie::SetUpFilter (Boolean which)        {
  1454. /* purpose: Shows how to set up an ActionFilter.
  1455. **            In this sample the filter is used to resize the window
  1456. **            when the controller is hidden to show badges.            */
  1457.  
  1458.         MovieController        localMC          = GetController();
  1459.         Boolean                mine          = true,
  1460.                             defaultFilter = !mine /* Use Apple's */;
  1461.         MCActionFilter        whichFilter      =
  1462.                                 (which == mine) ? (MCActionFilter) &MCFilter : nil;
  1463.  
  1464.     return ( MCSetActionFilter(localMC, whichFilter) );
  1465.  
  1466. }    /* SetUpFilter */
  1467.  
  1468.  
  1469.  
  1470. ComponentResult        CMovie::ShowBadge (Boolean doShow)        {
  1471. /* purpose: Shows how to use the MCDoAction routine to
  1472. **            select the behavior of the controller.        */
  1473.  
  1474.         Boolean                params    = doShow;
  1475.         MovieController        localMC = GetController();
  1476.  
  1477.         
  1478. // The action mcActionSetUseBadge takes a boolean as the parameter:
  1479.     return ( MCDoAction(localMC, mcActionSetUseBadge, (void*) params) );
  1480.  
  1481. }    /* ShowBadge */
  1482.  
  1483.  
  1484.  
  1485. ComponentResult        CMovie::EnableKeys (Boolean doEnable)    {
  1486.  
  1487.         Boolean                params    = doEnable;
  1488.         MovieController        localMC = GetController();
  1489.  
  1490.         
  1491. // The action mcActionSetKeysEnabled takes a boolean as the parameter:
  1492.     return ( MCDoAction(localMC, mcActionSetKeysEnabled, (void*) params) );
  1493.  
  1494. }    /* EnableKeys */
  1495.  
  1496.  
  1497.  
  1498. // OVERRIDE
  1499. void    CMovie::Activate (void)        {
  1500.  
  1501.         MovieController        localMC   = GetController();
  1502.         GrafPtr                localPort = GetMacPort();
  1503.  
  1504.  
  1505.     inherited::Activate();        // Calls ForceNextPrepare & sets CView::active.
  1506.  
  1507.     justActivated = true;        // For my special CView::DispatchCursor.
  1508.     
  1509.     if (localMC)    {
  1510.         Prepare();                /* ... since MCActivate draws directly
  1511.                                 **       in the Port.  Also calls SetPort. */
  1512.         MCActivate(localMC, localPort, true);
  1513.     }
  1514.     
  1515. }    /* Activate */
  1516.  
  1517.  
  1518.  
  1519. // OVERRIDE
  1520. void    CMovie::Deactivate (void)    {
  1521.  
  1522.         MovieController        localMC   = GetController();
  1523.         GrafPtr                localPort = GetMacPort();
  1524.  
  1525.  
  1526.     inherited::Deactivate();
  1527.  
  1528.     if (localMC)    {
  1529.         Prepare();
  1530.         MCActivate(localMC, localPort, false);
  1531.     }
  1532.  
  1533. }    /* Deactivate */
  1534.  
  1535.  
  1536.  
  1537. // OVERRIDE
  1538. void    CMovie::Draw (Rect *area)    {
  1539.  
  1540.         Movie                localMoov = GetMovie();
  1541.         MovieController        localMC   = GetController();
  1542.         GrafPtr                localPort = GetMacPort();
  1543.  
  1544.  
  1545.     if (localMC != nil)        {
  1546.             /* Will update any attached Movie: */
  1547.             MCDraw(localMC, localPort);
  1548.      }
  1549.      
  1550.     else if (localMoov != nil)    {
  1551.             UpdateMovie(localMoov);
  1552.     }
  1553.  
  1554.  //    else    inherited::Draw(area);    --    CPane::Draw is empty.
  1555.     
  1556. }    /* Draw */
  1557.  
  1558.  
  1559.  
  1560. // OVERRIDE
  1561. void    CMovie::DoClick (Point hitPt, short modifierKeys, long when)    {
  1562. /* With the Badge showing and therefore the Controller Bar NOT,
  1563. ** MCClick does all the work ... double clicking somewhere in
  1564. ** the Movie, but NOT on the badge, causes the Movie to play ...
  1565. ** clicking on the Badge causes the Controller Bar to appear and
  1566. ** the Badge to disappear.
  1567. **
  1568. ** With the Controller Bar showing and therefore the Badge NOT,
  1569. ** clicking in the Controller Bar is also totally handled by MCClick.
  1570. ** Samo Samo for clicking in the Movie above the Controller Bar with
  1571. ** no <Option Key> pressed.  But, courtesy of yours truly, if the
  1572. ** <Option Key> IS pressed, the Controller Bar disappears.  If the
  1573. ** Controller Bar is not visible, QuickTime makes the Badge re-appear: */
  1574.  
  1575.         Movie                localMoov  = GetMovie();
  1576.         MovieController        localMC       = GetController();
  1577.         ComponentResult        mcVis       = MCGetVisible(localMC);
  1578.         Boolean                usingBadge = false,
  1579.                             toggle       = (mcVis == 0) ? true : false;
  1580.         GrafPtr                localPort  = GetMacPort();
  1581.         LongRect            moovFox;
  1582.         Rect                moovQox, windRect;
  1583.         LongPt                framePt;
  1584.         Point                windPt;
  1585.  
  1586.     
  1587.     if (localMC)    {
  1588.     
  1589.         QDToFrame(hitPt, &framePt);
  1590.         FrameToWind(&framePt, &windPt);
  1591.         if (mcVis == 0)
  1592.             MCClick(localMC, localPort, windPt, when, modifierKeys);
  1593.             
  1594.         else /* Controller is visible */    {
  1595.             /* You would also come here if the entire Movie had been cut
  1596.             ** or cleared or if you had simply created a brand new Movie.
  1597.             ** The latter creates a new Movie whose box has zero-extent
  1598.             ** = {1,1,1,1}.  The Movie's duration is also set = 0.        */
  1599.             
  1600.             if (localMoov && GetMovieDuration(localMoov) > 0)    {
  1601.                 GetMovieBox(localMoov, &moovQox);
  1602.                 FailOSErr( GetMoviesError() );
  1603.                 QDToFrameR(&moovQox, &moovFox);
  1604.                 FrameToWindR(&moovFox, &windRect);
  1605.                 if ( PtInRect(windPt, &windRect) )        {
  1606.                     if ( MCDoAction(localMC, mcActionGetUseBadge, &usingBadge) ==
  1607.                          (ComponentResult) noErr )    {
  1608.  
  1609.                         if ( (modifierKeys & optionKey) && usingBadge )
  1610.                             // Automatically makes the Badge appear or disappear:
  1611.                             MCSetVisible(localMC, toggle);
  1612.                         else
  1613.                             MCClick(localMC, localPort, windPt, when, modifierKeys);
  1614.                     
  1615.                     }
  1616.                     else
  1617.                         MCClick(localMC, localPort, windPt, when, modifierKeys);
  1618.                 }
  1619.                 else    {
  1620.                     /* Clicked on the Controller Bar itself,
  1621.                     ** vice just on the Movie above it:        */
  1622.                     MCClick(localMC, localPort, windPt, when, modifierKeys);
  1623.                 }
  1624.             }    /* Got a Movie */
  1625.             
  1626.         }    /* Controller is visible */
  1627.         
  1628.     }    /* localMC */
  1629.  
  1630.     else    inherited::DoClick(hitPt, modifierKeys, when);    // EMPTY for now !!
  1631.  
  1632. }    /* DoClick */
  1633.  
  1634.  
  1635.  
  1636. // OVERRIDE
  1637. void    CMovie::DoKeyDown (char theChar, Byte keyCode, EventRecord *macEvent)    {
  1638.  
  1639.         MovieController        localMC           = GetController();
  1640.         Boolean                keysEnabled       = false;
  1641.         short                localModifiers = macEvent->modifiers;
  1642.  
  1643.  
  1644.     if (localMC)    {
  1645.         if ( MCDoAction(localMC, mcActionGetKeysEnabled, &keysEnabled) ==
  1646.              (ComponentResult) noErr )
  1647.             if (keysEnabled)    MCKey(localMC, keyCode, localModifiers);
  1648.     }
  1649.     
  1650.     /*
  1651.     ** MUST pass up the chain to CBureaucrat which implements:
  1652.     **
  1653.     **            itsSupervisor->DoKeyDown(...);
  1654.     **
  1655.     ** where this "itsSupervisor" is my CQuickTime document.
  1656.     ** Since a CDocument is a CBureaucrat, CBureaucrat::DoKeyDown
  1657.     ** gets called AGAIN.  This time, however, "itsSupervisor" is
  1658.     ** my application since a CApplication supervises a CDocument.
  1659.     **
  1660.     ** In short, I must pass DoKeyDown UP to my application:
  1661.     */
  1662.     inherited::DoKeyDown(theChar, keyCode, macEvent);
  1663.     
  1664. }    /* DoKeyDown */
  1665.  
  1666.  
  1667.  
  1668. // OVERRIDE
  1669. void    CMovie::Dawdle (long *maxSleep)        {
  1670.  
  1671.         Movie                localMoov = GetMovie();
  1672.         MovieController        localMC      = GetController();
  1673.  
  1674.  
  1675.     inherited::Dawdle(maxSleep);                    // Currently EMPTY !!!
  1676.  
  1677.     *maxSleep = maxMilliSecToUse;
  1678.     
  1679.     if (localMC != nil)        {
  1680.         if (MCIdle(localMC) == mcHandledEvent)        // Calls MoviesTask.
  1681.             ;
  1682.      // MCDoAction(localMC, mcActionShowBalloon, &gBalloonsUp);  --  NOT needed ???
  1683.     }
  1684.     
  1685.     else if (localMoov != nil)    MoviesTask(localMoov, maxMilliSecToUse);
  1686.  
  1687. }    /* Dawdle */
  1688.  
  1689.  
  1690.  
  1691. /*********************************************************************************
  1692.  DispatchCursor
  1693.  
  1694.     Mouse is inside view and the cursor shape needs to be adjusted.  Find out
  1695.     if a subview can set the cursor shape. If not, send message to ourself to
  1696.     handle it.
  1697.         
  1698.     According to the TCL Manual, AdjustCursor get called ONLY when we leave our
  1699.     CPane AND re-enter.  Looking at the original TCL source code as well as
  1700.     "following the bouncing ball" via the TCL Debugger, it is clear that we are
  1701.     called everytime even if the blasted mouse has NOT moved.  Symantec's Tech
  1702.     Support has confirmed this.  My suspicion is that the TCL Manual was written
  1703.     when DispatchCursor was called in response to a "mouseMovedMessage" Event
  1704.     generated by _WaitNextEvent.  To correct this deficiency, I rewrote
  1705.     DispatchCursor so that it does simulate a "mouseMovedMessage" Event.
  1706.  
  1707.     Do NOT rewrite TCL's CView::DispatchCursor for your own program; rather write
  1708.     CYourView::DispatchCursor or CYourPane::DispatchCursor.  Only Symantec should
  1709.     fiddle with TCL's CView method.
  1710.  
  1711.  *********************************************************************************/
  1712.  
  1713.     /*
  1714.     **    Find area of View not covered by subviews:
  1715.     */
  1716.         static void        SubView_Frame (CView *theView, RgnHandle uncovered)        {
  1717.  
  1718.                 LongRect    frameR;
  1719.                 Rect        globalR;
  1720.                 
  1721.                 
  1722.             if (theView->IsVisible()  &&  theView->wantsClicks)        {
  1723.                 theView->GetFrame(&frameR);
  1724.                 theView->FrameToGlobalR(&frameR, &globalR);
  1725.                 RectRgn(gUtilRgn, &globalR);
  1726.                 DiffRgn(uncovered, gUtilRgn, uncovered);
  1727.             }
  1728.             
  1729.         }    /* SubView_Frame */
  1730.  
  1731.  
  1732.  
  1733. void    CMovie::DispatchCursor (
  1734.     Point        where,                    /* Mouse location in Window coords    */
  1735.     RgnHandle    mouseRgn)                /* Region containing the mouse        */
  1736. {
  1737.         CView                *hitView;    /* View containing the mouse        */
  1738.         LongRect            frameAperture;
  1739.         Rect                globalAperture;
  1740.         RgnHandle            apertureRgn;
  1741.         static RgnHandle    prevMouseRgn = NULL;
  1742.         GrafPtr                savePort;
  1743.         static GrafPtr        prevWindow     = NULL;
  1744.         Point                saveOrigin, offsetOrigin, offsetGlobal, globWhere;
  1745.         Boolean                mouseHasMoved, firstTime;
  1746.     
  1747.     
  1748.     hitView = FindSubview(where);        /* See if mouse is within a subview. */
  1749.     
  1750.     if (hitView == NULL)    {            /* Mouse not within a deeper subview,
  1751.                                         ** but within THIS one.                 */
  1752.  
  1753.      // Wish I could avoid all this memory overhead, but ...
  1754.         apertureRgn = NewRgn();
  1755.         GetAperture(&frameAperture);    /* Start off with the aperture */
  1756.                                         /*   in global coordinates.       */
  1757.         FrameToGlobalR(&frameAperture, &globalAperture);
  1758.         RectRgn(apertureRgn, &globalAperture);
  1759.         
  1760.         // Calculate the uncovered area of this View:
  1761.         if (itsSubviews != NULL)    {    /* Substract the area covered by */
  1762.                                         /*   the frames of its subviews     */
  1763.             itsSubviews->DoForEach1((EachFunc1) SubView_Frame, (long)apertureRgn);
  1764.         }
  1765.  
  1766.         /* Now take intersection with the visRgn of View's port.  There could
  1767.         ** be something, such as a window, floating above the View. Unfortunately,
  1768.         ** the visRgn is the local coordinates and we need it to be in global
  1769.         ** coordinates.  Rather than making a copy and offsetting to global
  1770.         ** coords, we temporily shift the View's port so that its local coords
  1771.         ** are the same as global coords. This saves us the overhead of making
  1772.         ** a copy of the visRgn, which may take up a lot of memory, at the
  1773.         ** expense of having to save and restore the port and origin.            */
  1774.                                         
  1775.         GetPort(&savePort);                /* Save port and origin. */
  1776.         SetPort(macPort);
  1777.                 
  1778.         offsetOrigin = saveOrigin = topLeft(macPort->portRect);
  1779.         
  1780.         LocalToGlobal(&offsetOrigin);
  1781.         SetOrigin(offsetOrigin.h, offsetOrigin.v);
  1782.                                           /* visRgn is in Global coords now. */
  1783.         SectRgn(macPort->visRgn, apertureRgn, apertureRgn);
  1784.         
  1785.                                         /* Restore origin and port. */
  1786.         SetOrigin(saveOrigin.h, saveOrigin.v);
  1787.         SetPort(savePort);
  1788.         
  1789.         offsetGlobal = topLeft( (**((WindowPeek)macPort)->contRgn).rgnBBox );
  1790.         globWhere = where;
  1791.         globWhere.h += offsetGlobal.h;
  1792.         globWhere.v += offsetGlobal.v;
  1793.  
  1794.         firstTime = (macPort != prevWindow) || justSaved || justActivated;
  1795.         
  1796.         if (firstTime)        {
  1797.             if (prevMouseRgn == NULL)    prevMouseRgn = NewRgn();
  1798.             CopyRgn(mouseRgn, prevMouseRgn);
  1799.         }
  1800.         ;
  1801.         mouseHasMoved = !EqualRgn(mouseRgn, prevMouseRgn) ||
  1802.                         !PtInRgn(globWhere, prevMouseRgn);
  1803.         if (firstTime || mouseHasMoved)    {
  1804.             CopyRgn(apertureRgn, mouseRgn);
  1805.             AdjustCursor(where, mouseRgn);
  1806.             CopyRgn(mouseRgn, prevMouseRgn);
  1807.         }
  1808.         ;
  1809.         prevWindow = macPort;
  1810.         justSaved = false;
  1811.         justActivated = false;
  1812.                 
  1813.      /*
  1814.      ** gUtilRgn is a universally available RgnHandle that is setup
  1815.      ** by CApplication::IApplication via a call to NewRgn and is
  1816.      ** NOT and need not be disposed of by the TCL.  The final call
  1817.      ** to _ExitToShell tacked onto the end of the compiled code
  1818.      ** will automatically dispose of any handles on the Application
  1819.      ** heap.  The same holds true for gApplication, gBartender,
  1820.      ** gClipboard, gGopher and the remaining global objects.
  1821.      **
  1822.      ** DisposeRgn(gUtilRgn);
  1823.      */
  1824.         SetEmptyRgn(gUtilRgn);            // Do this instead !!
  1825.         DisposeRgn(apertureRgn);        // We're finished with this also.
  1826.      /* DisposeRgn(prevMouseRgn);        // Let _ExitToShell take care of
  1827.      **                                    //   this since I still need it.  */
  1828.         
  1829.     }
  1830.     else    {                            /* Mouse is within a subview. */
  1831.         hitView->DispatchCursor(where, mouseRgn);
  1832.     }
  1833.  
  1834.     /* If balloons are on and no one has shown a balloon, then do it now.
  1835.     ** This could either be because the mouse is not in a subview or because
  1836.     ** no subview did help. This allows a group of panes to share the same help
  1837.     ** balloon by putting the help info in their enclosing view.                */
  1838.  
  1839.     if (gSystem.hasHelpMgr && HMGetBalloons() && !cCurrHelpView)    {            
  1840.         
  1841.             Rect                r;
  1842.             HMMessageRecord        helpData;
  1843.             Point                  globalMouse;
  1844.             Ptr                    tipProc = NULL;
  1845.             short                bProc, bVariant, bMethod;
  1846.     
  1847.     
  1848.         helpData.hmmHelpType = 0;
  1849.         GetBalloonInfo(&helpData, &globalMouse, &r, &tipProc,
  1850.                        &bProc, &bVariant, &bMethod); 
  1851.         
  1852.         ShowHelpBalloon(&helpData, globalMouse, &r, tipProc,
  1853.                         bProc, bVariant, bMethod);
  1854.     }
  1855.     
  1856. }    /* DispatchCursor */
  1857.  
  1858.  
  1859.  
  1860. // OVERRIDE
  1861. void    CMovie::AdjustCursor (Point where, RgnHandle mouseRgn)        {
  1862. /* This seems as good a place as any for a tracing lesson:
  1863. **
  1864. ** IPaneX() calls CalcAperture which calls itsEnclosure->GetAperture.  Since
  1865. ** itsEnclosure is of class CWindow, we are calling CWindow::GetAperture which
  1866. ** sets the aperture = the portRect, offset so the topLeft of the aperture = {0, 0}.
  1867. ** CalcAperture continues by converting the aperture returned by GetAperture to
  1868. ** frame coordinates.  CalcAperture then computes the intersection of the frame &
  1869. ** the returned aperture and fills in the instance variable = CPane::aperture.
  1870. **
  1871. ** BUT ... initially the frame = nil since we passed width = height = 0 to IPane(...).
  1872. ** However, after calling IPane, we call FitToEnclosure.  The latter retrieves the
  1873. ** Window's interior = portRect and converts it to frame coordinates.  FitToEnclosure
  1874. ** finishes by calling ChangeSize and passes to the latter the window's portRect in
  1875. ** frame coordinates.  ChangeSize calls ResizeFrame which sets the width, height and
  1876. ** frame instance variables of CPane accordingly ... so we've got a finite frame
  1877. ** finally.  CalcAperture gets called AGAIN so we get a finite aperture as well.
  1878. **
  1879. ** How does my CMovie's AdjustCursor finally get called?  When IPane is called by
  1880. ** IMovie, IView gets called to setup CView::itsEnclosure and
  1881. ** CBureaucrat::itsSupervisor.  IPane then calls IPaneX() which calls:
  1882. **                        itsEnclosure->AddSubView(this);
  1883. ** where "this" = my CMovie CPane and itsEnclosure = my window.  AddSubView
  1884. ** initializes CView::itsSubViews by calling IList and adds "this" to the CList =
  1885. ** itsSubViews.
  1886. **
  1887. ** Within CApplication::Run():
  1888. **                        itsSwitchboard->ProcessEvent();
  1889. ** is called.  The latter calls:
  1890. **                        gDesktop->DispatchCursor(...);
  1891. ** which calls CWindow's DispatchCursor which then calls CView's DispatchCursor.
  1892. ** The latter calls FindSubView and upon finding that the mouse is within my
  1893. ** CMovie CPane, returns hitView = CMovie CPane.  hitView->DispatchCursor is called
  1894. ** and since hitView = CMovie, in effect CMovie->DispatchCursor is being called.
  1895. ** CMovie has no DispatchCursor method, so this method is inherited from CView.
  1896. ** The object that was sent the message = DispatchCursor is my CMovie, so when CView's
  1897. ** DispatchCursor finds no more sub-views, the latter calls AdjustCursor.  This
  1898. ** call could have been written:
  1899. **                        this->AdjustCursor(...);
  1900. ** where "this" = the object that was sent the ORIGINAL message = DispatchCursor.
  1901. ** Since "this" = my CMovie, my CMovie::AdjustCursor gets called.
  1902. **
  1903. ** According to the TCL Manual, we get called ONLY when we leave this CMovie pane
  1904. ** AND re-enter.  We called GetCCursor once and ONLY once within our IStarterApp
  1905. ** and will call SetCCursor any number of times below.  All of this is according
  1906. ** to the Hoyle stipulated in IM V.
  1907. **
  1908. ** What I have NOT been able to figure out yet is how we get called ONLY when we
  1909. ** leave this CMovie pane AND re-enter.  Looking at the original TCL source code
  1910. ** as well as "following the bouncing ball" via the TCL Debugger, it appears that
  1911. ** we are called everytime even if the blasted mouse has NOT moved.  Symantec has
  1912. ** confirmed this.  My suspicion is that the TCL Manual was written when
  1913. ** DispatchCursor was called in response to a "mouseMovedMessage" Event generated
  1914. ** by _WaitNextEvent.  To correct this deficiency, I rewrote DispatchCursor so
  1915. ** that it does simulate a "mouseMovedMessage" Event.                             */
  1916.  
  1917.      // #define kCameraCursor    3006
  1918.      
  1919.         Movie            localMoov  = GetMovie();
  1920.         Rect            mouseRect, moovBox, globalRect;
  1921.         LongPt            locWhere;
  1922.         LongRect        moovFRect, framePart;
  1923.         
  1924.         
  1925.     if (localMoov == NULL)        {
  1926.         inherited::AdjustCursor(where, mouseRgn);        // Calls SetCursor(&arrow).
  1927.         return;
  1928.     }
  1929.  
  1930.     // Get the WHOLE frame at first, but just the visible portion:
  1931.     GetFrame(&framePart);
  1932.     SectLongRect(&framePart, &aperture, &framePart);
  1933.     ;
  1934.     // Now just the visible part of the Movie:
  1935.     GetMovieBox(localMoov, &moovBox);
  1936.  // FailOSErr( GetMoviesError() );    --    NO danger here !!
  1937.     QDToFrameR(&moovBox, &moovFRect);
  1938.     SectLongRect(&moovFRect, &aperture, &moovFRect);
  1939.     ;
  1940.     WindToFrame(where, &locWhere);
  1941.         
  1942.     if ( PtInLongRect(&locWhere, &moovFRect) )    {
  1943.         if (niftyCameraCRSR != NULL) /* We've got a color Mac. */ {
  1944.                 LoadResource(niftyCameraCRSR);            // May have been purged.
  1945.                 SetCCursor(niftyCameraCRSR);
  1946.         }
  1947.         else    SetCursor(*gCameraCursor);
  1948.         framePart.bottom = moovFRect.bottom;
  1949.     }
  1950.     else /* in just the Controller Bar */    {
  1951.         SetCursor(&arrow);
  1952.         framePart.top = moovFRect.bottom;
  1953.     }
  1954.     
  1955.     /* Change the passed "mouseRgn" so that my newly rewritten
  1956.     ** DispatchCursor calls AdjustCursor ONLY if the mouse has moved: */
  1957.     
  1958.     FrameToGlobalR(&framePart, &globalRect);            // Convert to global coords â€¦
  1959.     RectRgn(mouseRgn, &globalRect);
  1960.  
  1961. }    /* AdjustCursor */
  1962.  
  1963.  
  1964.  
  1965. // OVERRIDE
  1966. void    CMovie::UpdateMenus (void)    {
  1967.  
  1968.         Movie                localMoov    = GetMovie();
  1969.         MovieController        localMC        = GetController();
  1970.         TimeValue            atBeginning    = 0, lengthMovie,
  1971.                             currSelectionTime, currSelectionDuration,
  1972.                             currentTime, nextTime, nextDuration;
  1973.         Fixed                movieRate;
  1974.         short                allMedia    = 0;
  1975.         OSType                allTypes    = 0;
  1976.         
  1977.         
  1978.     inherited::UpdateMenus();     // Enable standard commands.
  1979.     
  1980.     ShiftKeyIsDownToSelectWholeMovie = KeyIsDown(KeyShift);
  1981.     
  1982.     if (localMC)    {
  1983.     
  1984.         if ( MCIsEditingEnabled(localMC) )        {
  1985.         
  1986.             /*
  1987.             ** Has NOT been Cut or Cleared or NOT a new window.
  1988.             ** Note that I also change the text of each MENU item
  1989.             ** because I prefer such phrases as "Nothing to Cut"
  1990.             ** in each MENU item when appropriate.
  1991.             **
  1992.             ** Also note that placing such phrases just in the
  1993.             ** attached resource file is NOT ample because once
  1994.             ** SetCmdText is called, the MENU resource loaded
  1995.             ** in memory stays that way.  Therefore, I need to
  1996.             ** call SetCmdText for all items, even if disabled.
  1997.             **
  1998.             ** Anyway, I thought that overall it's a nice feature.
  1999.             */
  2000.         
  2001.             if (localMoov)        lengthMovie = GetMovieDuration(localMoov);
  2002.             else                lengthMovie = -1;
  2003.             
  2004.             if (lengthMovie > 0)    {
  2005.                 if (ShiftKeyIsDownToSelectWholeMovie)
  2006.                     gBartender->SetCmdText(cmdCut, "\pCut Entire Movie");
  2007.                 else
  2008.                     gBartender->SetCmdText(cmdCut, "\pCut Movie Frame(s)");
  2009.                 gBartender->EnableCmd(cmdCut);
  2010.                 ;
  2011.                 if (ShiftKeyIsDownToSelectWholeMovie)
  2012.                     gBartender->SetCmdText(cmdCopy, "\pCopy Entire Movie");
  2013.                 else
  2014.                     gBartender->SetCmdText(cmdCopy, "\pCopy Movie Frame(s)");
  2015.                 gBartender->EnableCmd(cmdCopy);
  2016.                 ;
  2017.                 if (ShiftKeyIsDownToSelectWholeMovie)
  2018.                     gBartender->SetCmdText(cmdClear, "\pClear Entire Movie");
  2019.                 else
  2020.                     gBartender->SetCmdText(cmdClear, "\pClear Movie Frame(s)");
  2021.                 gBartender->EnableCmd(cmdClear);
  2022.             }
  2023.             else    {
  2024.                 gBartender->SetCmdText(cmdCut, "\pNothing to Cut");
  2025.                 gBartender->SetCmdText(cmdCopy, "\pNothing to Copy");
  2026.                 gBartender->SetCmdText(cmdClear, "\pNothing to Clear");        
  2027.             }
  2028.         
  2029.             // Can Paste into an empty Movie:
  2030.             if (gClipboard->DataSize('moov') > 0)    {
  2031.                 if (ShiftKeyIsDownToSelectWholeMovie)
  2032.                     gBartender->SetCmdText(cmdPaste, "\pPaste over Entire Movie");
  2033.                 else
  2034.                     gBartender->SetCmdText(cmdPaste, "\pPaste over Movie Frame(s)");
  2035.                 gBartender->EnableCmd(cmdPaste);
  2036.             }
  2037.             else
  2038.                 gBartender->SetCmdText(cmdPaste, "\pNothing to Paste");
  2039.                 
  2040.             /*
  2041.             ** inherited::UpdateMenus() propagates up to CBureaucrat::UpdateMenus
  2042.             ** which calls:
  2043.             **                itsSupervisor->UpdateMenus();
  2044.             ** Since "itsSupervisor" is my CQuickTime document,
  2045.             ** CQuickTime::UpdateMenus gets called.  The latter calls:
  2046.             **                CDocument::UpdateMenus();
  2047.             ** which, if CDocument::lastTask != NULL, calls:
  2048.             **                CDocument::UpdateUndo().
  2049.             ** UpdateUndo sets the text of the Edit MENU's "Undo" item to
  2050.             ** "Undo Cut" or "Undo Paste", for example.  In short, normally
  2051.             ** we do NOT need this here because it is duplicative.  However,
  2052.             ** because of my innovative changing of item text as addressed
  2053.             ** above, I need it here.  The only reason I need to duplicate
  2054.             ** the code here is for the case, lastTask = NULL; otherwise,
  2055.             ** UpdateUndo changes the text for me.
  2056.             */
  2057.  
  2058.             if (lastMovieEditTask == NULL)        {
  2059.                 gBartender->SetCmdText(cmdUndo, "\pNothing to Undo");        
  2060.             }
  2061.  
  2062.          /* else    {
  2063.                 gBartender->EnableCmd(cmdUndo);
  2064.                 ( (CQuickTime*) itsSupervisor )->UpdateUndo();
  2065.             }                                                   */
  2066.         
  2067.         }    /* editing is enabled */
  2068.         
  2069.         gBartender->SetCmdText(cmdClose, "\pClose Movie");
  2070.         
  2071.         if (lengthMovie > 0)    {
  2072.  
  2073.             GetMovieSelection(localMoov, &currSelectionTime, &currSelectionDuration);
  2074.             FailOSErr( GetMoviesError() );
  2075.             currentTime = GetMovieTime(localMoov, nil);
  2076.             FailOSErr( GetMoviesError() );
  2077.             movieRate = GetMovieRate(localMoov);
  2078.             FailOSErr( GetMoviesError() );
  2079.             GetMovieNextInterestingTime(localMoov, nextTimeMediaSample,
  2080.                                         allMedia, &allTypes, currentTime,
  2081.                                         movieRate, &nextTime, &nextDuration);
  2082.             FailOSErr( GetMoviesError() );
  2083.             ;
  2084.             gBartender->EnableCmd(cmdPlayForward);
  2085.             gBartender->EnableCmd(cmdPlayBackward);
  2086.             if (currentTime != atBeginning)
  2087.                 gBartender->EnableCmd(cmdGoToBeginning);
  2088.             if (nextTime > 0)            // See comment within CMovie::SetSelection.
  2089.                 gBartender->EnableCmd(cmdGoToEnd);
  2090.             gBartender->EnableCmd(cmdGoToFrameNumber);
  2091.             gBartender->EnableCmd(cmdSelectFrames);
  2092.             if (currSelectionDuration > 0)
  2093.                 gBartender->EnableCmd(cmdDeselectFrames);
  2094.  
  2095.         }
  2096.         
  2097.     }    /* localMC */
  2098.  
  2099. }    /* UpdateMenus */
  2100.  
  2101.  
  2102.  
  2103. void    CMovie::SetSelection (long theCommand)        {
  2104. /* The various editing routines such as MCCut & MCClear work with
  2105. ** the current selection, so we set the selection accordingly:      */
  2106.     
  2107.  
  2108.         Movie                activeMoov    = GetMovie();
  2109.         MovieController        activeMC    = GetController();
  2110.         TimeValue            start, duration, lengthMovie,
  2111.                             currSelectionTime, currSelectionDuration, currentTime,
  2112.                             nextTime, nextDuration;
  2113.         short                allMedia    = 0;
  2114.         OSType                allTypes    = 0;
  2115.         Fixed                movieRate;
  2116.  
  2117.  
  2118.  // if (activeMC == NULL || activeMoov == NULL)        return;  --  canNOT happen !!
  2119.     
  2120.     lengthMovie = GetMovieDuration(activeMoov);
  2121.     FailOSErr( GetMoviesError() );
  2122.  /* Bet you thought I forgot about pasting into an empty Movie.
  2123.  ** NOT !!! because for an empty Movie, there is no selection.    */
  2124.     if (lengthMovie == 0)    return;
  2125.     
  2126.     GetMovieSelection (activeMoov, &currSelectionTime, &currSelectionDuration);
  2127.     FailOSErr( GetMoviesError() );
  2128.         
  2129.     if ( !ShiftKeyIsDownToSelectWholeMovie /* just a frame or two */ )    {
  2130.         if (currSelectionDuration > 0 && currSelectionDuration <= lengthMovie)    {
  2131.             /* Frame(s) already selected.  The user can force a
  2132.             ** selection of discrete frame(s) by clicking on either
  2133.             ** the <Forward> or <Backward> "Step" controls that are
  2134.             ** part of the Controller Bar while simultaneously pressing
  2135.             ** the <Shift> key, the 'ole' "Shift-Select" bit.
  2136.             **
  2137.             ** If you feel so inclined, use the "Select Frames" item
  2138.             ** under the "Movie" Menu as a simpler way to accomplish
  2139.             ** the same thing.                                            */
  2140.             
  2141.             FramesPreSelected = true;
  2142.             ;
  2143.             start = currSelectionTime;
  2144.             duration = currSelectionDuration;
  2145.         }
  2146.         else /* select the frame you're staring at */    {
  2147.         
  2148.             FramesPreSelected = false;
  2149.  
  2150.             if (theCommand == cmdPaste)        {
  2151.                 duration = 0;
  2152.              /* Go forward one frame because unless we're at
  2153.              ** the very end of the Movie, the currentTime is
  2154.              ** the time BEFORE the viewed frame.  The goal is
  2155.              ** to always paste AFTER the viewed frame.  If
  2156.              ** we're at the bitter end, advancing one frame
  2157.              ** has no effect, so our goal is still achieved.    */
  2158.                 MCDoAction(activeMC, mcActionStep, (void*) ((Fixed)1));
  2159.                 start = GetMovieTime(activeMoov, nil);
  2160.                 FailOSErr( GetMoviesError() );                    
  2161.             }
  2162.             
  2163.             else /* cutting, copying or clearing */        {
  2164.                 currentTime = GetMovieTime (activeMoov,
  2165.                                             nil /* don't need TimeRecord */);
  2166.                 FailOSErr( GetMoviesError() );
  2167.                 movieRate = GetMovieRate(activeMoov);
  2168.                 FailOSErr( GetMoviesError() );
  2169.                 GetMovieNextInterestingTime(activeMoov, nextTimeMediaSample,
  2170.                                             allMedia, &allTypes, currentTime,
  2171.                                             movieRate, &nextTime, &nextDuration);
  2172.                 FailOSErr( GetMoviesError() );
  2173.                 if (nextTime > 0 /* && nextTime <= lengthMovie */)    {
  2174.                     start = currentTime;
  2175.                     duration = nextTime - currentTime;
  2176.                 }
  2177.                 else    {
  2178.                     /* There's an apparent problem ??FEATURE?? at the very
  2179.                     ** end of the Movie because when you step either forward
  2180.                     ** to or backward from the end, the last frame shows
  2181.                     ** TWICE.  This last frame does not exist twice, it just
  2182.                     ** appears twice.  In this instance, "nextTime" is negative.
  2183.                     ** This problem does NOT occur at the beginning, that is,
  2184.                     ** the first frame does not show twice.                        */
  2185.                     
  2186.                     // ... so go the bitter end & THEN backup:
  2187.                     GoToEndOfMovie(activeMoov);
  2188.                     FailOSErr( GetMoviesError() );
  2189.                     MCDoAction(activeMC, mcActionStep, (void*) ((Fixed)-1));
  2190.                     start = GetMovieTime(activeMoov, nil);
  2191.                     FailOSErr( GetMoviesError() );
  2192.                     duration = lengthMovie - start;
  2193.                 }
  2194.             }    /* NOT pasting */
  2195.             
  2196.         }    /* just select one frame */
  2197.     }
  2198.         
  2199.     else /* <Shift> key pressed to select the WHOLE thing! */    {
  2200.         start = 0;
  2201.         duration = lengthMovie;
  2202.     }
  2203.         
  2204.     SetMovieSelection(activeMoov, start, duration);
  2205.     FailOSErr( GetMoviesError() );
  2206.  /*
  2207.  ** We do NOT have to reset the <Shift> key Boolean because
  2208.  ** the TCL always calls UpdateMenus in response to either
  2209.  ** a mouseDown in the MenuBar or a <CMD> keypress:
  2210.  
  2211.     ShiftKeyIsDownToSelectWholeMovie = false;
  2212.  */
  2213.     
  2214. }    /* SetSelection */
  2215.  
  2216.  
  2217.  
  2218. void    CMovie::ClearSelection (void)        {
  2219. /* The following is for pasting ONLY.
  2220. ** It is NOT required for disposing:  */
  2221.  
  2222.         CWindow                *movieWindow = GetWindow();
  2223.         short                numWindows;
  2224.         Str255                Untitled     = "\pUntitled",
  2225.                             numString,
  2226.                             newTitle;
  2227.         MovieController        activeMC     = GetController();
  2228.         Movie                activeMoov     = GetMovie();
  2229.         TimeValue            currentTime, movieDuration;
  2230.  
  2231.     
  2232.     /* The if-clause IS necessary since CMovie::UpdateMenus
  2233.     ** enables "Paste" given a 'MooV' on the clipboard and
  2234.     ** since cmdPaste calls ClearSelection:                */
  2235.     
  2236.     if (
  2237.         activeMC != NULL                  &&
  2238.         activeMoov != NULL                  &&
  2239.         GetMovieDuration(activeMoov) > 0
  2240.        )    {
  2241.         // Otherwise, nothing to clear
  2242.         GetMovieSelection(activeMoov, ¤tTime, &movieDuration);
  2243.         FailOSErr( GetMoviesError() );
  2244.         if (movieDuration > 0)    {
  2245.             MCClear(activeMC);
  2246.             FailOSErr( GetMoviesError() );
  2247.         }
  2248.     }
  2249.         
  2250.     /* Do NOT change window's title because I call this when pasting.
  2251.     
  2252.     numWindows = ++(gDecorator->wCount);    // See comments within INewQuickTime.
  2253.     NumToString(numWindows, numString);
  2254.     CopyPString(Untitled, newTitle);
  2255.     ConcatPStrings(newTitle, "\p - ");
  2256.     ConcatPStrings(newTitle, numString);
  2257.     movieWindow->SetTitle(newTitle);
  2258.     */
  2259.  
  2260. }    /* ClearSelection */
  2261.  
  2262.  
  2263.  
  2264. // OVERRIDE
  2265. void    CMovie::DoCommand (long theCommand)        {
  2266.  
  2267.         enum
  2268.         {
  2269.             okGoTo = cmdOK, cancelGoTo,            // "Go To Frame" DLOG ...
  2270.             iconGoTo = 3,
  2271.             goToEdit,
  2272.             
  2273.             okSelect = cmdOK, cancelSelect,        // "Select Frames" DLOG ...
  2274.             iconSelect = 3,
  2275.             selectFromStat, selectFromEdit,
  2276.             selectToStat, selectToEdit
  2277.         };
  2278.                 
  2279.         Movie                activeMoov, scrapMoov;
  2280.         MovieController        activeMC;
  2281.         TimeValue            atBeginning      = 0,
  2282.                             noSelection      = 0,
  2283.                             lengthMovie,
  2284.                             currSelectionTime, currSelectionDuration,
  2285.                             currentTime, nextTime,
  2286.                             fromTime, toTime,
  2287.                             newDuration, nextDuration;
  2288.         Fixed                movieRate;
  2289.         short                allMedia      = 0;
  2290.         OSType                allTypes      = 0;
  2291.         CWindow                *theWindow      = GetWindow();
  2292.         GrafPtr                localPort      = GetMacPort();
  2293.         OSErr                err;
  2294.         long                zeroFlags      = 0, dlogCommand;
  2295.         CQuickTime            *myDoc          = (CQuickTime*) GetSupervisor();
  2296.         Boolean                prevDirty;
  2297.         CMovieDLOGDir        *movieDLOGDir = NULL;
  2298.         CIntegerText        *goToText, *selectFromText, *selectToText;
  2299.         long                goToValue, selectFromValue, selectToValue,
  2300.                             frameCount, swap;
  2301.         
  2302.  
  2303.     /* This should NOT happen because UpdateMenus will NOT
  2304.     ** enable any Edit MENU items if active Controller = NULL: */
  2305.     if ( myDoc->itsMovie == NULL    ||
  2306.          (activeMC = GetController()) == NULL )    {
  2307.         inherited::DoCommand(theCommand);
  2308.         return;
  2309.     }
  2310.     
  2311.     /* Note that I do NOT test for a zero-duration "activeMoov" because
  2312.     ** pasting still works for such a beast.  With regards to cutting,
  2313.     ** copying and clearing, CMovie::UpdateMenus will disable these
  2314.     ** commands for an empty Movie so they don't apply anyway.            */
  2315.     
  2316.     activeMoov    = GetMovie();
  2317.     
  2318.     switch (theCommand)        {
  2319.     
  2320.      /* Will eventually propagate up to CDocument::DoCommand
  2321.      
  2322.         case cmdUndo:
  2323.         
  2324.             if (lastTask != NULL)    {
  2325.                 if (undone)        lastTask->Redo();
  2326.                 else            lastTask->Undo();
  2327.  
  2328.                 undone = !undone;
  2329.                 UpdateUndo();
  2330.             }
  2331.         
  2332.             break;
  2333.      */
  2334.         case cmdCut:
  2335.         
  2336.         /* Returns a new copy of the attached Movie, so after we place
  2337.         ** the copy on the public Scrap we must dispose of it.  We can
  2338.         ** dispose of the cut or removed Movie because PutMovieOnScrap
  2339.         ** creates a new Movie based on the one cut ... so the one
  2340.         ** placed on the Scrap is in addition to our "scrapMoov".
  2341.         **
  2342.         ** If you selected the ENTIRE Movie by pressing the <Shift> key
  2343.         ** while making your Menu selection, the duration of the original
  2344.         ** Movie, the one that was cut, is set = 0; however, the "moov"
  2345.         ** still exists and so does the Movie Controller = "mc".
  2346.         ** Furthermore, if you tried to open a new Movie file with the
  2347.         ** file having the cut Movie still open, the name of the latter
  2348.         ** would NOT appear in the SFGetFile list because it's still
  2349.         ** there even if its duration = 0.
  2350.         **
  2351.         ** Oh ... one more thing ... MCCut and MCClear will send a
  2352.         ** mcActionControllerSizeChanged message to my MCFilter which
  2353.         ** resizes my window accordingly.  Note that the window will be
  2354.         ** VERY short if you selected the WHOLE Movie because there's no
  2355.         ** longer a Movie attached to the Controller.  Furthermore, the
  2356.         ** sizebox disappears because the Movie is gone.  There's nothing
  2357.         ** to resize, right?  RIGHT!!                                      */
  2358.  
  2359.             /*
  2360.             theWindow->HideSuspend();        ** Initially, I did the ugly stuff
  2361.                                             ** off-screen.  Later I decided that
  2362.                                             ** it didn't look bad at all.
  2363.             */
  2364.         
  2365.             SetSelection(cmdCut);
  2366.  
  2367.             /* Fill in CMovie::lastMovieEditTask,
  2368.             ** record the current Scrap for UNdoing
  2369.             ** and record the in-place Movie: */
  2370.             MakeMovieEditTask(cmdCut);
  2371.  
  2372.             scrapMoov = MCCut(activeMC);
  2373.             FailOSErr( GetMoviesError() );
  2374.             
  2375.             /* Clear existing Scrap before adding +
  2376.             ** Copy Movie and MoviePoster in 'PICT' format: */
  2377.             err = PutMovieOnScrap(scrapMoov, zeroFlags);
  2378.             FailOSErr(err);
  2379.             
  2380.             /* Dispose of the original Scrap because PutMovieOnScrap
  2381.             ** creates a copy and places the copy on the Scrap.         */
  2382.             DisposeMovie(scrapMoov);
  2383.             FailOSErr( GetMoviesError() );
  2384.  
  2385.             /* Notify propagates up to CBureaucrat::Notify which calls:
  2386.             **                itsSupervisor->Notify(...);
  2387.             ** So CDocument::Notify gets called and the latter sets
  2388.             ** CDocument::lastTask = the passed editTask after it
  2389.             ** disposes of the previous lastTask if there's one.
  2390.             ** Remember, IDocument sets lastTask = NULL.  Notify also
  2391.             ** sets CDocument's undone to FALSE and dirty to TRUE.        */
  2392.     
  2393.             Notify(lastMovieEditTask);
  2394.             lastMovieEditTask->Do();
  2395.                                     
  2396.             // Where we're at !!!
  2397.             GetMovieSelection(activeMoov, &currSelectionTime, &currSelectionDuration);
  2398.             FailOSErr( GetMoviesError() );
  2399.             SetMovieSelection(activeMoov, currSelectionTime, noSelection);
  2400.             FailOSErr( GetMoviesError() );
  2401.             Activate();
  2402.  
  2403.          // theWindow->ShowResume();
  2404.             
  2405.             break;    /* cmdCut */
  2406.             
  2407.         case cmdCopy:
  2408.         
  2409.             SetSelection(cmdCopy);
  2410.             
  2411.             MakeMovieEditTask(cmdCopy);
  2412.  
  2413.             scrapMoov = MCCopy(activeMC);
  2414.             FailOSErr( GetMoviesError() );
  2415.             FailOSErr( PutMovieOnScrap(scrapMoov, zeroFlags) );
  2416.             
  2417.             DisposeMovie(scrapMoov);            // Get rid of the 1st copy after a
  2418.             FailOSErr( GetMoviesError() );        //   2nd copy is placed on the Scrap.
  2419.             
  2420.             prevDirty = myDoc->dirty;
  2421.             ;
  2422.             Notify(lastMovieEditTask);
  2423.             ;
  2424.             /* If the doc was previously dirty, for example, from
  2425.             ** a Paste operation, then we should maintain it:      */
  2426.             myDoc->dirty = prevDirty;            // ... otherwise, Mr. CLEAN !!!
  2427.             lastMovieEditTask->Do();
  2428.             
  2429.             currentTime = GetMovieTime(activeMoov, nil);
  2430.             FailOSErr( GetMoviesError() );
  2431.             ;
  2432.             if (ShiftKeyIsDownToSelectWholeMovie || !FramesPreSelected)
  2433.             {
  2434.                 SetMovieSelection(activeMoov, currentTime, noSelection);
  2435.                 FailOSErr( GetMoviesError() );
  2436.                 Activate();
  2437.             }
  2438.             else
  2439.             {
  2440.                 // Leave selection alone !!
  2441.             }
  2442.  
  2443.             break;    /* cmdCopy */
  2444.             
  2445.         case cmdPaste:                
  2446.             
  2447.             /* Pasting really does look ugly WHEN we've selected the
  2448.             ** ENTIRE Movie and there's a Movie already there.  In this
  2449.             ** instance ClearSelection will call MCClear which resizes
  2450.             ** the window down.  MCPaste below will resize the window
  2451.             ** back up ... I didn't like seeing two changes in size.    */
  2452.             
  2453.             if (ShiftKeyIsDownToSelectWholeMovie)        theWindow->HideSuspend();
  2454.  
  2455.             SetSelection(cmdPaste);
  2456.             
  2457.             MakeMovieEditTask(cmdPaste);
  2458.  
  2459.             /* First get rid of what's preselected, if anything.
  2460.             ** The QuickTime docs state that MCPaste is analogous
  2461.             ** to PasteMovieSelection which will paste OVER any
  2462.             ** pre-selected frames.  I have discovered that this
  2463.             ** does NOT appear to be true.                          */
  2464.             
  2465.             ClearSelection();
  2466.  
  2467.             scrapMoov = NewMovieFromScrap(newMovieActive);
  2468.             FailOSErr( GetMoviesError() );
  2469.             ;
  2470.             MCPaste(activeMC,scrapMoov);
  2471.             FailOSErr( GetMoviesError() );
  2472.  
  2473.             DisposeMovie(scrapMoov);
  2474.             FailOSErr( GetMoviesError() );
  2475.             
  2476.             Notify(lastMovieEditTask);
  2477.             lastMovieEditTask->Do();
  2478.  
  2479.             GetMovieSelection(activeMoov, &currSelectionTime, &currSelectionDuration);
  2480.             FailOSErr( GetMoviesError() );
  2481.             SetMovieSelection(activeMoov, currSelectionTime, noSelection);
  2482.             FailOSErr( GetMoviesError() );
  2483.             Activate();
  2484.  
  2485.             if (ShiftKeyIsDownToSelectWholeMovie)
  2486.                 // Generates an update Event:
  2487.                 theWindow->ShowResume();
  2488.             
  2489.             break;    /* cmdPaste */
  2490.             
  2491.         case cmdClear:
  2492.         
  2493.             SetSelection(cmdClear);
  2494.             
  2495.             MakeMovieEditTask(cmdClear);
  2496.  
  2497.             /* Once again, if I've chosen to clear the WHOLE Movie
  2498.             ** by pressing the <Shift> key, the  resulting Movie's
  2499.             ** duration is set = 0.  However, the Movie is NOT and
  2500.             ** SHOULD not be disposed of.  Note that I do NOT call
  2501.             ** PutMovieOnScrap so the existing contents of the
  2502.             ** public Scrap remain intact:                           */
  2503.             
  2504.             MCClear(activeMC);
  2505.             FailOSErr( GetMoviesError() );
  2506.             
  2507.             Notify(lastMovieEditTask);
  2508.             lastMovieEditTask->Do();
  2509.             
  2510.             GetMovieSelection(activeMoov, &currSelectionTime, &currSelectionDuration);
  2511.             FailOSErr( GetMoviesError() );
  2512.             SetMovieSelection(activeMoov, currSelectionTime, noSelection);
  2513.             FailOSErr( GetMoviesError() );
  2514.             Activate();
  2515.             
  2516.             break;    /* cmdClear */
  2517.             
  2518.         case cmdPlayForward:
  2519.         
  2520.          // HideCursor();    --     not this time, folks !!!
  2521.             
  2522.             /* Stop the Movie just in case it is playing.
  2523.             ** Call MCDoAction rather than StopMovie so the
  2524.             ** Pause Button on the Movie Controller bar
  2525.             ** changes back to a Play Button:                */
  2526.             MCDoAction(activeMC, mcActionPlay, (void*) 0 /* = stop Movie */);
  2527.             FailOSErr( GetMoviesError() );
  2528.             GoToBeginningOfMovie(activeMoov);
  2529.             FailOSErr( GetMoviesError() );
  2530.             movieRate = GetMoviePreferredRate(activeMoov);
  2531.             FailOSErr( GetMoviesError() );
  2532.             /* Do this, rather than call StartMovie, in order to
  2533.             ** display the Pause button on the Movie Controller bar: */
  2534.             MCDoAction(activeMC, mcActionPlay, (void*) movieRate);
  2535.  
  2536.             break;    /* cmdPlayForward */
  2537.                         
  2538.         case cmdPlayBackward:
  2539.         
  2540.             MCDoAction(activeMC, mcActionPlay, (void*) 0);
  2541.             FailOSErr( GetMoviesError() );
  2542.             GoToEndOfMovie(activeMoov);
  2543.             FailOSErr( GetMoviesError() );
  2544.             movieRate = GetMoviePreferredRate(activeMoov);
  2545.             FailOSErr( GetMoviesError() );
  2546.             MCDoAction(activeMC, mcActionPlay, (void*) -movieRate);
  2547.  
  2548.             break;    /* cmdPlayBackward */
  2549.                         
  2550.         case cmdGoToBeginning:
  2551.         
  2552.             MCDoAction(activeMC, mcActionPlay, (void*) 0);
  2553.             FailOSErr( GetMoviesError() );
  2554.             GoToBeginningOfMovie(activeMoov);
  2555.             FailOSErr( GetMoviesError() );
  2556.  
  2557.             break;    /* cmdGoToBeginning */
  2558.                         
  2559.         case cmdGoToEnd:
  2560.         
  2561.             MCDoAction(activeMC, mcActionPlay, (void*) 0);
  2562.             FailOSErr( GetMoviesError() );
  2563.             GoToEndOfMovie(activeMoov);
  2564.             FailOSErr( GetMoviesError() );
  2565.             
  2566.             break;    /* cmdGoToEnd */
  2567.                         
  2568.         case cmdGoToFrameNumber:
  2569.  
  2570.             movieDLOGDir = new (CMovieDLOGDir);
  2571.             movieDLOGDir->IMovieDLOGDir(kGoToFrame);
  2572.  
  2573.             /*
  2574.             ** IMovieDLOGDir calls IDLOGDirector which:
  2575.             **
  2576.             **     (a) sets CDirector::CDialogDirector::CDLOGDirector->itsWindow =
  2577.             **                                                    new(CDLOGDialog);
  2578.             **     (b) calls IDLOGDialog which calls AddDITLItems
  2579.             **     (c) AddDITLItems then sets each View's ID =
  2580.             **           the item's index in the DITL resource.
  2581.             */
  2582.  
  2583.             goToText = (CIntegerText*) movieDLOGDir->FindViewByID(goToEdit);
  2584.             goToText->SetIntValue(1);
  2585.  
  2586.             movieDLOGDir->BeginDialog();
  2587.             dlogCommand = movieDLOGDir->DoModalDialog(okGoTo);
  2588.             if (dlogCommand == okGoTo)
  2589.             {
  2590.                 goToValue = goToText->GetIntValue();
  2591.  
  2592.                 if ( movieDLOGDir->Close(false /* NOT quitting */) )
  2593.                 {    // Inherited from CDialogDirector
  2594.                     
  2595.                     theWindow->HideSuspend();
  2596.                     ;
  2597.                     GoToBeginningOfMovie(activeMoov);
  2598.                     FailOSErr( GetMoviesError() );
  2599.                     lengthMovie = GetMovieDuration(activeMoov);
  2600.                     FailOSErr( GetMoviesError() );
  2601.                     for (frameCount = 1; frameCount < goToValue; frameCount++)
  2602.                     {
  2603.                         currentTime = GetMovieTime(activeMoov, nil);
  2604.                         FailOSErr( GetMoviesError() );
  2605.                         if (currentTime == lengthMovie)
  2606.                         {    /* Beyond the end.  Note that MCDoAction will NOT
  2607.                             ** bomb; however, needless time will be consumed. */
  2608.                             SysBeep(10);
  2609.                             break;
  2610.                         }
  2611.                         MCDoAction(activeMC, mcActionStep, (void*) ((Fixed) 1));
  2612.                     }
  2613.                     ;
  2614.                     theWindow->ShowResume();
  2615.                     
  2616.                 }    /* Validation successful, so close the Dialog window */
  2617.                 else
  2618.                 {
  2619.                     /* Validation not successful, so keep
  2620.                     ** window open and post an alert      */
  2621.                     SysBeep(10);
  2622.                 }
  2623.             }
  2624.             
  2625.             else /* Cancel */
  2626.             {
  2627.              // SysBeep(10);  --  already done by CMovieDLOGDir::DoCommand
  2628.                 movieDLOGDir->itsWindow->Dispose();
  2629.             }
  2630.         
  2631.             break;    /* cmdGoToFrameNumber */
  2632.                         
  2633.         case cmdSelectFrames:
  2634.  
  2635.             movieDLOGDir = new (CMovieDLOGDir);
  2636.             movieDLOGDir->IMovieDLOGDir(kSelectFrames);
  2637.             ;
  2638.             selectFromText = (CIntegerText*) movieDLOGDir->
  2639.                                              FindViewByID(selectFromEdit);
  2640.             selectFromText->SetIntValue(1);
  2641.             selectToText = (CIntegerText*) movieDLOGDir->FindViewByID(selectToEdit);
  2642.             selectToText->SetIntValue(1);
  2643.  
  2644.             movieDLOGDir->BeginDialog();
  2645.             dlogCommand = movieDLOGDir->DoModalDialog(okSelect);
  2646.             if (dlogCommand == okSelect)
  2647.             {
  2648.                 selectFromValue = selectFromText->GetIntValue();
  2649.                 selectToValue = selectToText->GetIntValue();
  2650.                 if (selectFromValue > selectToValue)
  2651.                 {
  2652.                     swap = selectFromValue;
  2653.                     selectFromValue = selectToValue;
  2654.                     selectToValue = swap;
  2655.                 }
  2656.                                 
  2657.                 if ( movieDLOGDir->Close(false) )
  2658.                 {
  2659.                     currentTime = atBeginning;
  2660.                     movieRate = GetMovieRate(activeMoov);
  2661.                     FailOSErr( GetMoviesError() );
  2662.                     ;
  2663.                     for (
  2664.                           frameCount = 1;
  2665.                           frameCount < selectFromValue;        // before the Frame.
  2666.                           frameCount++
  2667.                         )
  2668.                     {
  2669.                         GetMovieNextInterestingTime(activeMoov, nextTimeMediaSample,
  2670.                                                     allMedia, &allTypes, currentTime,
  2671.                                                     movieRate, &nextTime,
  2672.                                                     &nextDuration);
  2673.                         FailOSErr( GetMoviesError() );
  2674.                         if (nextTime < 0)            break;        // beyond the end.
  2675.                         currentTime = nextTime;
  2676.                     }
  2677.                     fromTime = currentTime;
  2678.                     ;
  2679.                     currentTime = atBeginning;
  2680.                     for (
  2681.                           frameCount = 1;
  2682.                           frameCount <= selectToValue;        // after the Frame.
  2683.                           frameCount++
  2684.                         )
  2685.                     {
  2686.                         if (currentTime < 0)        break;        // beyond the end.
  2687.                         GetMovieNextInterestingTime(activeMoov, nextTimeMediaSample,
  2688.                                                     allMedia, &allTypes, currentTime,
  2689.                                                     movieRate, &nextTime,
  2690.                                                     &nextDuration);
  2691.                         FailOSErr( GetMoviesError() );
  2692.                         currentTime = nextTime;
  2693.                     }
  2694.                     if (currentTime < 0)        toTime = lengthMovie;
  2695.                     else                        toTime = currentTime;
  2696.                     ;
  2697.                     GetMovieSelection(activeMoov, &currSelectionTime,
  2698.                                       &currSelectionDuration);
  2699.                     FailOSErr( GetMoviesError() );
  2700.                     newDuration = toTime - fromTime;
  2701.                     SetMovieSelection(activeMoov, fromTime, newDuration);
  2702.                     FailOSErr( GetMoviesError() );
  2703.                     Activate();
  2704.                     
  2705.                 }    /* Validation successful, so close the Dialog window */
  2706.                 else
  2707.                 {
  2708.                     /* Validation not successful, so keep
  2709.                     ** window open and post an alert      */
  2710.                     SysBeep(10);
  2711.                 }
  2712.             }
  2713.             
  2714.             else if (dlogCommand == cmdSelectAll)
  2715.             {
  2716.                 movieDLOGDir->itsWindow->Dispose();
  2717.  
  2718.                 lengthMovie = GetMovieDuration(activeMoov);
  2719.                 FailOSErr( GetMoviesError() );
  2720.                 SetMovieSelection(activeMoov, atBeginning, lengthMovie);
  2721.                 FailOSErr( GetMoviesError() );
  2722.                 Activate();
  2723.             }
  2724.             
  2725.             else /* Cancel */
  2726.             {
  2727.              // SysBeep(10);  --  already done by CMovieDLOGDir::DoCommand
  2728.                 movieDLOGDir->itsWindow->Dispose();
  2729.             }
  2730.         
  2731.             break;    /* cmdSelectFrames */
  2732.                         
  2733.         case cmdDeselectFrames:
  2734.             
  2735.             GetMovieSelection(activeMoov, &currSelectionTime, &currSelectionDuration);
  2736.             FailOSErr( GetMoviesError() );
  2737.             SetMovieSelection(activeMoov, currSelectionTime, noSelection);
  2738.             FailOSErr( GetMoviesError() );
  2739.             Activate();
  2740.             
  2741.             break;    /* cmdDeselectFrames */
  2742.                         
  2743.         default:
  2744.             inherited::DoCommand(theCommand);
  2745.             break;
  2746.                 
  2747.     }    /* end: switch */
  2748.  
  2749. }    /* DoCommand */
  2750.  
  2751.  
  2752.  
  2753. void    CMovieFile::IMovieFile (void)    {
  2754.  
  2755.  
  2756.     inherited::IResFile();
  2757.  // refNum = noMoovFile;        --        IResFile sets = 0.
  2758.      resID = noMoovResource;
  2759.  
  2760. }    /* IMovieFile */
  2761.  
  2762.  
  2763.  
  2764. // OVERRIDE
  2765. void    CMovieFile::CreateNew (OSType creator, OSType fType)    {
  2766.  
  2767.         FSSpec        movieSpec;
  2768.         Movie        theMoov = theMovie->GetMovie();
  2769.         short        rsrcID    = 0;        // Assign new unique ID.
  2770.  
  2771.  
  2772.     GetFSSpec(&movieSpec);
  2773.     FlattenMovie(
  2774.                   theMoov,
  2775.                   flattenAddMovieToDataFork /* for transfer to NON-Macs */,
  2776.                   &movieSpec,
  2777.                   creator,
  2778.                   iuSystemScript,
  2779.                   createMovieFileDeleteCurFile,
  2780.                   &rsrcID,
  2781.                   movieSpec.name
  2782.                 );
  2783.     FailOSErr( GetMoviesError() );
  2784.     resID = rsrcID;
  2785.  
  2786. }    /* CreateNew */
  2787.  
  2788.  
  2789.  
  2790. // OVERRIDE
  2791. void    CMovieFile::Open (SignedByte permission)    {
  2792.  
  2793.         FSSpec        movieSpec;
  2794.         OSErr        err;
  2795.         short        movieFileRefNum;
  2796.         
  2797.     
  2798.     if ( IsOpen() )        return;
  2799.     
  2800.     GetFSSpec(&movieSpec);
  2801.     err = OpenMovieFile(&movieSpec, &movieFileRefNum, permission);
  2802.     if (err == noErr)    refNum = movieFileRefNum;
  2803.     else                FailOSErr(err);                /* Never returns:
  2804.                                                     **     moov remains = nil &
  2805.                                                     **     refNum          = noMoovFile */
  2806. }    /* Open */
  2807.  
  2808.  
  2809.  
  2810. // OVERRIDE
  2811. void    CMovieFile::Close (void)    {
  2812.  
  2813.         short        localMoovRefNum = refNum;
  2814.         OSErr        err                = noErr;
  2815.         
  2816.         
  2817.     if (localMoovRefNum != noMoovFile)    {    // 'tis open.
  2818.         err = CloseMovieFile(localMoovRefNum);
  2819.         if (err == noErr)    {
  2820.             refNum = noMoovFile;            // Bye-Bye !!!
  2821.             resID = noMoovResource;
  2822.          // err = FlushVol("", volNum);        -- ONLY saving should write-to-disk.
  2823.         }
  2824.         FailOSErr(err);
  2825.     }
  2826.     
  2827.     /* IResFile::Close() checks to see if CResFile::refNum > 0 and,
  2828.     ** if so, closes the specified file.  Otherwise it does nothing.
  2829.     ** IF refNum were > 0, it would call CloseResFile(refNum)
  2830.     ** which does NOT pertain to a Movie file.  This is why we
  2831.     ** canNOT just call CResFile::Close and be done.                */
  2832.     
  2833.  // inherited::Close();
  2834.  
  2835. }    /* Close */
  2836.  
  2837.  
  2838.  
  2839. // OVERRIDE
  2840. void    CMovieFile::ThrowOut (void)        {
  2841.  
  2842.         FSSpec        movieSpec;
  2843.         
  2844.     
  2845.     Close();
  2846.     ;
  2847.     GetFSSpec(&movieSpec);
  2848.     FailOSErr( DeleteMovieFile(&movieSpec) );
  2849.     
  2850. }    /* ThrowOut */
  2851.  
  2852.  
  2853.     
  2854. // OVERRIDE
  2855. void    CMovieFile::ChangeName (Str63 newName)        {
  2856.  
  2857.         FSSpec        movieSpec;
  2858.         
  2859.     
  2860.     GetFSSpec(&movieSpec);
  2861.     FailOSErr( FSpRename(&movieSpec, newName) );
  2862.     ;
  2863.     CopyPString(newName, name);
  2864.  
  2865. }    /* ChangeName */
  2866.  
  2867.  
  2868.  
  2869. // OVERRIDE
  2870. void    CMovieFile::Update (void)    {
  2871.  
  2872.         Boolean        wasLocked;
  2873.         OSErr        err;
  2874.         Movie        localMoov = theMovie->GetMovie();
  2875.         FSSpec        theSpec;
  2876.         short        rsrcID      = 0;        // Assign new unique ID;
  2877.         
  2878.         
  2879.     ASSERT( IsOpen() );
  2880.     
  2881.     wasLocked = Lock(TRUE);
  2882.     ;
  2883.     if ( HasMovieChanged(localMoov) )
  2884.     {
  2885.         err = UpdateMovieResource(localMoov, refNum, resID, name);
  2886.         if (err != noErr)
  2887.         {
  2888.             Lock(wasLocked);
  2889.             FailOSErr(err);
  2890.         }
  2891.         GetFSSpec(&theSpec);
  2892.         FlattenMovie(
  2893.                       localMoov,
  2894.                       flattenAddMovieToDataFork,
  2895.                       &theSpec,
  2896.                       gSignature,
  2897.                       iuSystemScript,
  2898.                       createMovieFileDeleteCurFile,
  2899.                       &rsrcID,
  2900.                       theSpec.name
  2901.                     );
  2902.         err = GetMoviesError();
  2903.         if (err != noErr)
  2904.         {
  2905.             Lock(wasLocked);
  2906.             FailOSErr(err);
  2907.         }
  2908.         resID = rsrcID;
  2909.     }
  2910.     
  2911.     else
  2912.     {
  2913.         err = FlushVol("", volNum);
  2914.     }
  2915.     ;
  2916.     Lock(wasLocked);
  2917.     FailOSErr(err);
  2918.  
  2919. }    /* Update */
  2920.  
  2921.  
  2922.  
  2923. // OVERRIDE
  2924. void    CMovieFile::ResolveFileAlias (void)        {
  2925. /* Resolve the current File specification in case it is an alias.
  2926. ** Although the Finder and Standard File packages resolve aliases
  2927. ** for you, calling this method may be necessary if you open a file
  2928. ** directly. CFile's Specify methods call ResolveFileAlias for you. */
  2929.  
  2930.         OSErr            err;
  2931.         FSSpec            fileSpec;
  2932.         AliasHandle        alias;
  2933.         Boolean            isFolder, wasAliased, wasChanged;
  2934.     
  2935.     
  2936.     GetFSSpec(&fileSpec);
  2937.     
  2938.     if (gSystem.hasAliasMgr) /* System 7 */        {
  2939.     
  2940.         err = ResolveAliasFile(&fileSpec, true, &isFolder, &wasAliased);
  2941.         ;
  2942.         if (err == fnfErr)        {
  2943.         
  2944.             /* ????? */
  2945.             
  2946.         }
  2947.         else if (err != noErr)    {
  2948.             Failure (err, 0);
  2949.         }
  2950.         else /* NO error */        {
  2951.             if (wasAliased) /* copy back alias' specification */    {
  2952.                 CopyPString(fileSpec.name, name);
  2953.                 dirID = fileSpec.parID;
  2954.                 volNum = fileSpec.vRefNum;
  2955.             }
  2956.     
  2957.             // Raise exception if this is a directory since we handle only files:
  2958.             if (isFolder)        Failure(paramErr, 0);
  2959.         }
  2960.         
  2961.     }    /* System 7 */
  2962.     
  2963.     else if ( /* System 6 and */ QuickTimeIsInstalled() )    {
  2964.         // QuickTime has limited Alias Manager support for System 6:
  2965.     
  2966.         err = NewAlias(nil /* e.g., does not support relative path info */,
  2967.                        &fileSpec, &alias);
  2968.         ;
  2969.         if (alias != NULL)        {
  2970.             err = ResolveAlias(nil /* does not support relative path info */,
  2971.                                alias, &fileSpec /* target */, &wasChanged);
  2972.             ;
  2973.             if (err == fnfErr)    {
  2974.             
  2975.                 /* ????? */
  2976.                 
  2977.             }
  2978.             else if (err != noErr)    {
  2979.                 Failure (err, 0);
  2980.             }
  2981.             else /* NO error, so copy back info */        {
  2982.                 CopyPString(fileSpec.name, name);
  2983.                 dirID = fileSpec.parID;
  2984.                 volNum = fileSpec.vRefNum;
  2985.             }
  2986.         }    /* alias != NULL */
  2987.         
  2988.     }    /* System 6 && QuickTime */
  2989.     
  2990. }    /* ResolveFileAlias */
  2991.  
  2992.  
  2993.  
  2994. void    CMovie::MakeMovieEditTask (long theCommand)        {
  2995.  
  2996.         CMovieEditTask        *newEditTask  = NULL;
  2997.         
  2998.         
  2999.     TRY
  3000.     {
  3001.         newEditTask = new (CMovieEditTask);
  3002.         newEditTask->IMovieEditTask(this, theCommand, cFirstMovieEditTaskIndex);
  3003.     }
  3004.     CATCH
  3005.     {
  3006.         ForgetObject(newEditTask);
  3007.     }
  3008.     ENDTRY;
  3009.     
  3010.     lastMovieEditTask = newEditTask;
  3011.     
  3012. }    /* MakeMovieEditTask */
  3013.  
  3014.  
  3015.  
  3016. void    CMovieEditTask::IMovieEditTask (CMovie *thisMoviePane, long theCommand,
  3017.                                         short firstTaskIndex)    {
  3018.  
  3019.         // Moving memory:
  3020.         Movie                activeMoov, localMoov, localScrap;
  3021.         MovieController        activeMC;
  3022.         TimeValue            start = 0, movieLength, inputTime, inputDuration;
  3023.         OSErr                err;
  3024.         short                taskIndex;
  3025.  
  3026.  
  3027.     // Fill in some instance variables:
  3028.     
  3029.     if (theCommand == cmdRevert || theCommand == cmdPaste)        {
  3030.         activeMoov = thisMoviePane->GetMovie();
  3031.         activeMC = thisMoviePane->GetController();
  3032.         ;
  3033.         movieLength = GetMovieDuration(activeMoov);
  3034.         FailOSErr( GetMoviesError() );
  3035.         if (movieLength > 0)    {
  3036.             GetMovieSelection(activeMoov, &inputTime, &inputDuration);
  3037.             FailOSErr( GetMoviesError() );
  3038.             SetMovieSelection(activeMoov, start, movieLength);
  3039.             FailOSErr( GetMoviesError() );
  3040.             ;
  3041.             localMoov = MCCopy(activeMC);
  3042.             FailOSErr( GetMoviesError() );
  3043.             ;
  3044.             SetMovieSelection(activeMoov, inputTime, inputDuration);
  3045.             FailOSErr( GetMoviesError() );
  3046.         }
  3047.         else
  3048.             localMoov = NewMovie(newMovieActive);
  3049.         ;
  3050.         originalMoov = localMoov;
  3051.     }
  3052.     else
  3053.         originalMoov = NULL;
  3054.  
  3055.     if (theCommand == cmdCut || theCommand == cmdCopy)    {
  3056.         /* pasting and clearing do NOT affect the scrap */
  3057.         localScrap = NewMovieFromScrap(newMovieActive);
  3058.         err = GetMoviesError();
  3059.         if (err == noMoovOnScrap)    {
  3060.             /* QuickTime 1.0 returned a nil Movie with
  3061.             ** a err = noErr if zip in the Scrap. NO mo!! */
  3062.             err = noErr;
  3063.             localScrap = NULL;
  3064.         }
  3065.         FailOSErr(err);
  3066.         originalScrap = localScrap;
  3067.     }
  3068.     else
  3069.         originalScrap = NULL;
  3070.  
  3071.     editedMoviePane = thisMoviePane;
  3072.     editCmd = theCommand;
  3073.  
  3074.     if (firstTaskIndex > 0)
  3075.     {
  3076.         if (theCommand == cmdRevert)
  3077.             taskIndex = firstTaskIndex;
  3078.         else
  3079.             taskIndex = firstTaskIndex + theCommand - cmdCut + 1;
  3080.     }
  3081.     else taskIndex = 0;                /* This indicates we did NOT supply any
  3082.                                     ** strings at all in which case the Undo
  3083.                                     ** item will ALWAYS read just "Undo".     */
  3084.     inherited::ITask(taskIndex);
  3085.  
  3086. }    /* IMovieEditTask */
  3087.  
  3088.  
  3089.  
  3090. // OVERRIDE
  3091. void    CMovieEditTask::Do (void)    {
  3092.  
  3093.         Movie                activeMoov, localMoov, localScrap;
  3094.         MovieController        activeMC;
  3095.         TimeValue            start = 0, movieLength, inputTime, inputDuration;
  3096.         CMovie                *thisMoviePane = editedMoviePane;
  3097.         OSErr                err;
  3098.         
  3099.         
  3100.     // Fill in remaining instance variables:
  3101.     
  3102.     if (editCmd == cmdRevert || editCmd == cmdPaste)        {
  3103.         activeMoov = thisMoviePane->GetMovie();
  3104.         activeMC = thisMoviePane->GetController();
  3105.         ;
  3106.         movieLength = GetMovieDuration(activeMoov);
  3107.         FailOSErr( GetMoviesError() );
  3108.         if (movieLength > 0)    {
  3109.             GetMovieSelection(activeMoov, &inputTime, &inputDuration);
  3110.             FailOSErr( GetMoviesError() );
  3111.             SetMovieSelection(activeMoov, start, movieLength);
  3112.             FailOSErr( GetMoviesError() );
  3113.             ;
  3114.             localMoov = MCCopy(activeMC);
  3115.             FailOSErr( GetMoviesError() );
  3116.             ;
  3117.             SetMovieSelection(activeMoov, inputTime, inputDuration);
  3118.             FailOSErr( GetMoviesError() );
  3119.         }
  3120.         else
  3121.             localMoov = NewMovie(newMovieActive);
  3122.         ;
  3123.         newMoov = localMoov;
  3124.     }
  3125.     else
  3126.         newMoov = NULL;
  3127.  
  3128.     if (editCmd == cmdCut || editCmd == cmdCopy)    {
  3129.         /* pasting and clearing do NOT affect the scrap */
  3130.         localScrap = NewMovieFromScrap(newMovieActive);
  3131.         err = GetMoviesError();
  3132.         if (err == noMoovOnScrap)    {
  3133.             err = noErr;
  3134.             localScrap = NULL;
  3135.         }
  3136.         FailOSErr(err);
  3137.         newScrap = localScrap;
  3138.     }
  3139.     else
  3140.         newScrap = NULL;
  3141.  
  3142.  // inherited::Do();    --        EMPTY !!!
  3143.  
  3144. }    /* Do */
  3145.  
  3146.  
  3147.  
  3148. // OVERRIDE
  3149. void    CMovieEditTask::Undo (void)    {
  3150.  
  3151.         CQuickTime            *myDoc;
  3152.         OSErr                err;
  3153.         Movie                saveOriginalScrap, saveNewScrap, localScrap,
  3154.                             undoneMoov,
  3155.                             activeMoov = editedMoviePane->GetMovie();
  3156.         MovieController        activeMC   = editedMoviePane->GetController();
  3157.         TimeValue            noDuration = 0, movieLength, currentTime;
  3158.         CWindow                *theWindow = editedMoviePane->GetWindow();
  3159.         GrafPtr                localPort  = editedMoviePane->GetMacPort();
  3160.         long                zeroFlags  = 0;
  3161.         
  3162.         
  3163.     saveOriginalScrap = originalScrap;
  3164.     saveNewScrap = newScrap;
  3165.     
  3166.     switch (editCmd)    {
  3167.     
  3168.         case cmdCut:
  3169.         
  3170.          // theWindow->HideSuspend();  --  was NOT hidden when originally cut.
  3171.             ;
  3172.             MCUndo(activeMC);
  3173.             FailOSErr( GetMoviesError() );
  3174.             ;
  3175.          // theWindow->ShowResume();
  3176.         
  3177.             break;    /* cmdCut */
  3178.             
  3179.         case cmdCopy:
  3180.         
  3181.             /* Just need to swap out the scrap which
  3182.             ** we do following the switch-statement.  */
  3183.             
  3184.             break;    /* cmdCopy */
  3185.             
  3186.         case cmdRevert:
  3187.         /* Do the same as cmdPaste, with two immediate additions
  3188.         ** and some selection changes noted below:                */
  3189.         
  3190.             myDoc = (CQuickTime*) editedMoviePane->GetSupervisor();
  3191.             myDoc->dirty = !undone;
  3192.             justSaved = true;            // For my special CView::DispatchCursor.
  3193.  
  3194.         case cmdPaste:
  3195.         /* Weird things happen when UNdoing a paste operation
  3196.         ** wherein you pressed the <Shift> key to paste over an
  3197.         ** existing selection, whether said selection consists
  3198.         ** of several contiguous frames or the entire Movie.
  3199.         ** In these cases, UNdoing using MCUndo does not revert
  3200.         ** to what was there originally.  This is because I call
  3201.         ** MCClear on the existing selection before I paste.    */
  3202.         
  3203.             theWindow->HideSuspend();
  3204.             ;
  3205.             movieLength = GetMovieDuration(activeMoov);
  3206.             FailOSErr( GetMoviesError() );
  3207.             if (movieLength > 0)    {
  3208.                 SetMovieSelection(activeMoov, 0 /* at beginning */, movieLength);
  3209.                 FailOSErr( GetMoviesError() );
  3210.                 MCClear(activeMC);
  3211.                 FailOSErr( GetMoviesError() );
  3212.             }
  3213.             
  3214.             if ( !undone ) /* Undo */    undoneMoov = originalMoov;
  3215.             else           /* Redo */    undoneMoov = newMoov;
  3216.             
  3217.             movieLength = GetMovieDuration(undoneMoov);
  3218.             FailOSErr( GetMoviesError() );
  3219.             if (movieLength > 0)    {
  3220.                 SetMovieSelection(undoneMoov, 0, movieLength);
  3221.                 FailOSErr( GetMoviesError() );
  3222.                 MCPaste(activeMC, undoneMoov);
  3223.                 FailOSErr( GetMoviesError() );
  3224.                 if (editCmd == cmdRevert)    {
  3225.                     SetMovieSelection(activeMoov, 0, noDuration);        // Zip.
  3226.                     FailOSErr( GetMoviesError() );
  3227.                     GoToBeginningOfMovie(activeMoov);
  3228.                     FailOSErr( GetMoviesError() );
  3229.                 }
  3230.                 else /* cmdPaste */        {
  3231.                     currentTime = GetMovieTime(activeMoov, nil);
  3232.                     FailOSErr( GetMoviesError() );
  3233.                     SetMovieSelection(activeMoov, currentTime, noDuration);
  3234.                     FailOSErr( GetMoviesError() );
  3235.                     editedMoviePane->Activate();
  3236.                 }
  3237.             }
  3238.             ;
  3239.             theWindow->ShowResume();
  3240.             
  3241.             break;    /* cmdRevert & cmdPaste */
  3242.             
  3243.         case cmdClear:
  3244.         
  3245.          /*
  3246.          ** Doesn't look bad at all even though we hid
  3247.          ** the window when clearing the entire Movie:
  3248.          
  3249.             theWindow->HideSuspend();
  3250.          */
  3251.  
  3252.             MCUndo(activeMC);
  3253.             FailOSErr( GetMoviesError() );
  3254.  
  3255.          // theWindow->ShowResume();
  3256.         
  3257.             break;    /* cmdClear */
  3258.             
  3259.     }    /* end: switch */
  3260.  
  3261.     if ( (editCmd == cmdCut) || (editCmd == cmdCopy) )    {
  3262.         /*
  3263.         ** Only these Commands affect the Scrap.
  3264.         **
  3265.         ** MCUndo does NOT swap out the Scrap.  Specifically,
  3266.         ** MCUndo keeps the Scrap contents = newScrap:
  3267.         */
  3268.         if ( !undone ) /* Undo */    {
  3269.             if (originalScrap != NULL)    {
  3270.                 /* PutMovieOnScrap places a copy on the Scrap,
  3271.                 ** so we must dispose of the ORIGINAL original: */
  3272.                 localScrap = originalScrap;
  3273.                 FailOSErr( PutMovieOnScrap(localScrap, zeroFlags) );
  3274.                 DisposeMovie(originalScrap);
  3275.                 FailOSErr( GetMoviesError() );
  3276.             }
  3277.             else    FailOSErr( ZeroScrap() );
  3278.             ;
  3279.             localScrap = NewMovieFromScrap(newMovieActive);
  3280.             err = GetMoviesError();
  3281.             if (err == noMoovOnScrap)    {
  3282.                 err = noErr;
  3283.                 localScrap = NULL;
  3284.             }
  3285.             FailOSErr(err);
  3286.             originalScrap = localScrap;
  3287.             newScrap = saveNewScrap;
  3288.         }
  3289.         
  3290.         else /* Redo */        {
  3291.          // For cutting & copying, the newScrap is always != NULL:
  3292.          // if (newScrap != NULL)    {
  3293.                 localScrap = newScrap;
  3294.                 FailOSErr( PutMovieOnScrap(localScrap, zeroFlags) );
  3295.                 DisposeMovie(newScrap);                    // New copy now on Scrap.
  3296.                 FailOSErr( GetMoviesError() );
  3297.          // }
  3298.          // else    FailOSErr( ZeroScrap() );
  3299.             ;
  3300.             localScrap = NewMovieFromScrap(newMovieActive);
  3301.             err = GetMoviesError();
  3302.             if (err == noMoovOnScrap)    {
  3303.                 err = noErr;
  3304.                 localScrap = NULL;
  3305.             }
  3306.             FailOSErr(err);
  3307.             newScrap = localScrap;
  3308.             originalScrap = saveOriginalScrap;
  3309.         }
  3310.     }    /* cut or copy */
  3311.  
  3312.     inherited::Undo();        /* Toggles CTask::undone */
  3313.  
  3314. }    /* Undo */
  3315.  
  3316.  
  3317.  
  3318. // OVERRIDE
  3319. void    CMovieEditTask::Dispose (void)    {
  3320.  
  3321.  
  3322.     if (originalMoov != NULL && GetMovieDuration(originalMoov) > 0)        {
  3323.         DisposeMovie(originalMoov);
  3324.         FailOSErr( GetMoviesError() );
  3325.         originalMoov = NULL;
  3326.     }
  3327.     
  3328.     if (newMoov != NULL && GetMovieDuration(newMoov) > 0)    {
  3329.         DisposeMovie(newMoov);
  3330.         FailOSErr( GetMoviesError() );
  3331.         newMoov = NULL;
  3332.     }
  3333.     
  3334.     if (originalScrap != NULL)        {
  3335.         DisposeMovie(originalScrap);
  3336.         FailOSErr( GetMoviesError() );
  3337.         originalScrap = NULL;
  3338.     }
  3339.     
  3340.     if (newScrap != NULL)        {
  3341.         DisposeMovie(newScrap);
  3342.         FailOSErr( GetMoviesError() );
  3343.         newScrap = NULL;
  3344.     }
  3345.     
  3346.     inherited::Dispose();
  3347.  
  3348. }    /* Dispose */
  3349.  
  3350.  
  3351.  
  3352. CIconHandle        CRemoteIconPane::GetCICN (void)        {
  3353. /* So I can access the protected variable */
  3354.  
  3355.  
  3356.     return    (cicnH);
  3357.  
  3358. }    /* GetCICN */
  3359.  
  3360.  
  3361.  
  3362. void    CRemoteIconPane::SetCICN (CIconHandle theCICN)        {
  3363. /* So I can set the protected variable */
  3364.  
  3365.  
  3366.     cicnH = theCICN;
  3367.  
  3368. }    /* SetCICN */
  3369.  
  3370.  
  3371.  
  3372. // OVERRIDE
  3373. void    CRemoteIconPane::DoClick (Point hitPt, short modifierKeys, long when)    {
  3374.  
  3375.         CRemote                    *theDoc;
  3376.         CRemoteNullClickPane    *dimLit;        // Nothing personal, fella !!
  3377.         CIconHandle                lightOff;
  3378.         
  3379.  
  3380.     /* FindViewByID must start at the top to work,
  3381.     ** so begin with the CDocument supervisor:      */
  3382.     
  3383.     theDoc = (CRemote*) GetSupervisor();
  3384.     dimLit = (CRemoteNullClickPane*) theDoc->FindViewByID('lite');
  3385.     
  3386.     if (dimLit != NULL)
  3387.     {
  3388.         ForceNextPrepare();
  3389.         dimLit->Prepare();
  3390.         ;
  3391.         lightOff = dimLit->GetCICN();
  3392.         LoadResource(lightOn);
  3393.         dimLit->SetCICN(lightOn);
  3394.         dimLit->DrawIcon(FALSE);            // Turn light "on".
  3395.         ;
  3396.         ForceNextPrepare();
  3397.         /* this-> */Prepare();
  3398.     }
  3399.     
  3400.     if (Track())
  3401.     {
  3402.         itsSupervisor->DoCommand( GetClickCmd() );
  3403.     }
  3404.     
  3405.     if (dimLit != NULL)
  3406.     {
  3407.         ForceNextPrepare();
  3408.         dimLit->Prepare();
  3409.         ;
  3410.         dimLit->SetCICN(lightOff);
  3411.         dimLit->DrawIcon(FALSE);            // Turn "off".
  3412.         ;
  3413.         ForceNextPrepare();
  3414.         /* this-> */Prepare();
  3415.     }
  3416.  
  3417. }    /* DoClick */
  3418.  
  3419.  
  3420.  
  3421. // OVERRIDE
  3422. Boolean        CRemoteScrollPane::Track (void)        {
  3423. /* Continuously execute the clickCmd while
  3424. ** mouse is down inside the icon frame:        */
  3425.     
  3426.         Boolean        inBtn           = TRUE;
  3427.         Point        where;
  3428.         Rect        qdFrame;
  3429.         GrafPtr        scrollIconPort = macPort;
  3430.         
  3431.         
  3432.     DrawIcon(TRUE);
  3433.     
  3434.     FrameToQDR(&frame, &qdFrame);
  3435.  
  3436.     while ( StillDown() )
  3437.     {
  3438.         GetMouse(&where);
  3439.         ;
  3440.         if (PtInRect(where, &qdFrame))
  3441.         {
  3442.             if (!inBtn)        DrawIcon(TRUE);
  3443.             inBtn = TRUE;
  3444.         }
  3445.         else
  3446.         {
  3447.             if (inBtn)        DrawIcon(FALSE);
  3448.             inBtn = FALSE;
  3449.         }
  3450.         
  3451.         if (inBtn)
  3452.         {
  3453.             itsSupervisor->DoCommand( GetClickCmd() );
  3454.             // DoCommand above calls CQuickTime::itsMovie->Prepare().
  3455.             ForceNextPrepare();
  3456.             Prepare();
  3457.         }
  3458.     }
  3459.     
  3460.     if (inBtn)
  3461.     {
  3462.         ForceNextPrepare();
  3463.         Prepare();
  3464.         DrawIcon(FALSE);
  3465.     }
  3466.     
  3467.     // So CIconPane::DoClick does not execute the clickCmd AGAIN:
  3468.     return    (FALSE);
  3469.  
  3470. }    /* Track */
  3471.  
  3472.  
  3473.  
  3474. // OVERRIDE
  3475. void    CRemoteNullClickPane::DoClick (Point hitPt, short modifierKeys, long when)    {
  3476.  
  3477.     // Do zip !!!
  3478.     
  3479. }    /* DoClick */
  3480.  
  3481.  
  3482.  
  3483. void    CRemote::IRemote (CApplication *itsSupervisor)        {
  3484.  
  3485.         #define kRemoteHelp      5000
  3486.  
  3487.         Boolean                  savedAlloc;
  3488.         CWindow                  *smartWindow = NULL;
  3489.         Rect                  smartRect       = {0, 0, 350, 150};
  3490.         short                  hPos, vPos;
  3491.         CRemoteMainPane          *mainRemotePane;
  3492.         CRemoteNullClickPane  *light;
  3493.         CIconPane           /* *light, */ *eject, *load, *power,        // by row:
  3494.                               *pause, *stop,
  3495.                               *playBackward, *playForward,
  3496.                               *goToStart, /* *stepBackward, *stepForward, */ *goToEnd,
  3497.                            /* *volDown, *volUp, */
  3498.                               *logo;
  3499.         CRemoteScrollPane      *stepBackward, *stepForward,
  3500.                               *volDown, *volUp;
  3501.                 
  3502.         
  3503.     inherited::IDocument(itsSupervisor, false /* NOT printable */);
  3504.     
  3505.     smartWindow = new (CWindow);
  3506.     itsWindow = smartWindow;
  3507.     
  3508.     itsWindow->INewWindow(&smartRect, false /* NOT visible */,
  3509.                           rDocProc, true /* floating */,
  3510.                           false /* NO goAway box */,
  3511.                           (CFWDesktop*) gDesktop, this);
  3512.     ;
  3513.     /* CWindow::IWindowX sets minimum window size =
  3514.     ** CWindow::sizeRect.topLeft = {100, 100}        */
  3515.     itsWindow->sizeRect.top = smartRect.top;
  3516.     itsWindow->sizeRect.left = smartRect.left;
  3517.     ;
  3518.     itsWindow->SetTitle("\pRemote Control");
  3519.     ;
  3520.     itsWindow->SetHelpResID(kRemoteHelp);
  3521.  
  3522.     // The Main man ...
  3523.     mainRemotePane = new (CRemoteMainPane);
  3524.     mainRemotePane->IPane(
  3525.                            itsWindow,
  3526.                            this,
  3527.                            0, 0, 0, 0,
  3528.                            sizELASTIC, sizELASTIC
  3529.                          );
  3530.     mainRemotePane->FitToEnclosure(true, true);
  3531.     mainRemotePane->SetWantsClicks(TRUE);        // So the sub-Views see clicks.
  3532.     mainRemotePane->helpResIndex = 15;
  3533.     itsMainPane = mainRemotePane;
  3534.     
  3535.     // Next, turn on the lights:
  3536.     
  3537.     savedAlloc = SetAllocation(kAllocCanFail);
  3538.     lightOn = GetCIcon(kLightLight);
  3539.     SetAllocation(savedAlloc);
  3540.     FailNIL(lightOn);
  3541.     HPurge(lightOn);
  3542.     
  3543.     /* 1 */
  3544.     light = new (CRemoteNullClickPane);
  3545.     light->IIconPane(
  3546.                       mainRemotePane,
  3547.                       this,
  3548.                       5, 18,
  3549.                       sizFIXEDSTICKY, sizFIXEDSTICKY,
  3550.                       kDimLight,            /* cicn ID */
  3551.                       true                    /* fPreferColor */
  3552.                     );
  3553.     light->SetWantsClicks(TRUE);    // See comments within "CQuickTime.h"
  3554.     light->helpResIndex = 1;
  3555.     light->SetID('lite');
  3556.                 
  3557.     // Now for the remaining zillion sub-Views:
  3558.     
  3559.     /* 2 */
  3560.     eject = new (CRemoteIconPane);
  3561.     eject->IIconPane(
  3562.                       mainRemotePane,
  3563.                       this,
  3564.                       41, 18,
  3565.                       sizFIXEDSTICKY, sizFIXEDSTICKY,
  3566.                       kEject,                /* cicn ID */
  3567.                       true                    /* fPreferColor */
  3568.                     );
  3569.     eject->SetWantsClicks(TRUE);
  3570.     eject->SetClickCmd(kEject);
  3571.     eject->helpResIndex = 2;
  3572.                 
  3573.     /* 3 */
  3574.     load = new (CRemoteIconPane);
  3575.     load->IIconPane(
  3576.                      mainRemotePane,
  3577.                      this,
  3578.                      77, 18,
  3579.                      sizFIXEDSTICKY, sizFIXEDSTICKY,
  3580.                      kLoad, true
  3581.                    );
  3582.     load->SetWantsClicks(TRUE);
  3583.     load->SetClickCmd(kLoad);
  3584.     load->helpResIndex = 3;
  3585.                 
  3586.     /* 4 */
  3587.     power = new (CRemoteIconPane);
  3588.     power->IIconPane(
  3589.                       mainRemotePane,
  3590.                       this,
  3591.                       113, 18,
  3592.                       sizFIXEDSTICKY, sizFIXEDSTICKY,
  3593.                       kPower, true
  3594.                     );
  3595.     power->SetWantsClicks(TRUE);
  3596.     power->SetClickCmd(kPower);
  3597.     power->helpResIndex = 4;
  3598.     
  3599.     /* 5 */
  3600.     pause = new (CRemoteIconPane);
  3601.     pause->IIconPane(
  3602.                       mainRemotePane,
  3603.                       this,
  3604.                       33, 80,
  3605.                       sizFIXEDSTICKY, sizFIXEDSTICKY,
  3606.                       kPause, true
  3607.                     );
  3608.     pause->SetWantsClicks(TRUE);
  3609.     pause->SetClickCmd(kPause);
  3610.     pause->helpResIndex = 5;
  3611.                 
  3612.     /* 6 */
  3613.     stop = new (CRemoteIconPane);
  3614.     stop->IIconPane(
  3615.                      mainRemotePane,
  3616.                      this,
  3617.                      85, 80,
  3618.                      sizFIXEDSTICKY, sizFIXEDSTICKY,
  3619.                      kStop, true
  3620.                    );
  3621.     stop->SetWantsClicks(TRUE);
  3622.     stop->SetClickCmd(kStop);
  3623.     stop->helpResIndex = 6;
  3624.                 
  3625.     /* 7 */
  3626.     playBackward = new (CRemoteIconPane);
  3627.     playBackward->IIconPane(
  3628.                              mainRemotePane,
  3629.                              this,
  3630.                              33, 132,
  3631.                              sizFIXEDSTICKY, sizFIXEDSTICKY,
  3632.                              kPlayBackward, true
  3633.                            );
  3634.     playBackward->SetWantsClicks(TRUE);
  3635.     playBackward->SetClickCmd(kPlayBackward);
  3636.     playBackward->helpResIndex = 7;
  3637.                 
  3638.     /* 8 */
  3639.     playForward = new (CRemoteIconPane);
  3640.     playForward->IIconPane(
  3641.                             mainRemotePane,
  3642.                             this,
  3643.                             85, 132,
  3644.                             sizFIXEDSTICKY, sizFIXEDSTICKY,
  3645.                             kPlayForward, true
  3646.                           );
  3647.     playForward->SetWantsClicks(TRUE);
  3648.     playForward->SetClickCmd(kPlayForward);
  3649.     playForward->helpResIndex = 8;
  3650.                 
  3651.     /* 9 */
  3652.     goToStart = new (CRemoteIconPane);
  3653.     goToStart->IIconPane(
  3654.                           mainRemotePane,
  3655.                           this,
  3656.                           5, 184,
  3657.                           sizFIXEDSTICKY, sizFIXEDSTICKY,
  3658.                           kGoToStart, true
  3659.                         );
  3660.     goToStart->SetWantsClicks(TRUE);
  3661.     goToStart->SetClickCmd(kGoToStart);
  3662.     goToStart->helpResIndex = 9;
  3663.                 
  3664.     /* 10 */
  3665.     stepBackward = new (CRemoteScrollPane);
  3666.     stepBackward->IIconPane(
  3667.                              mainRemotePane,
  3668.                              this,
  3669.                              41, 184,
  3670.                              sizFIXEDSTICKY, sizFIXEDSTICKY,
  3671.                              kStepBackward, true
  3672.                            );
  3673.     stepBackward->SetWantsClicks(TRUE);
  3674.     stepBackward->SetClickCmd(kStepBackward);
  3675.     stepBackward->helpResIndex = 10;
  3676.                 
  3677.     /* 11 */
  3678.     stepForward = new (CRemoteScrollPane);
  3679.     stepForward->IIconPane(
  3680.                             mainRemotePane,
  3681.                             this,
  3682.                             77, 184,
  3683.                             sizFIXEDSTICKY, sizFIXEDSTICKY,
  3684.                             kStepForward, true
  3685.                           );
  3686.     stepForward->SetWantsClicks(TRUE);
  3687.     stepForward->SetClickCmd(kStepForward);
  3688.     stepForward->helpResIndex = 11;
  3689.                 
  3690.     /* 12 */
  3691.     goToEnd = new (CRemoteIconPane);
  3692.     goToEnd->IIconPane(
  3693.                         mainRemotePane,
  3694.                         this,
  3695.                         113, 184,
  3696.                         sizFIXEDSTICKY, sizFIXEDSTICKY,
  3697.                         kGoToEnd, true
  3698.                       );
  3699.     goToEnd->SetWantsClicks(TRUE);
  3700.     goToEnd->SetClickCmd(kGoToEnd);
  3701.     goToEnd->helpResIndex = 12;
  3702.                 
  3703.     /* 13 */
  3704.     volDown = new (CRemoteScrollPane);
  3705.     volDown->IIconPane(
  3706.                         mainRemotePane,
  3707.                         this,
  3708.                         33, 236,
  3709.                         sizFIXEDSTICKY, sizFIXEDSTICKY,
  3710.                         kVolumeDown, true
  3711.                       );
  3712.     volDown->SetWantsClicks(TRUE);
  3713.     volDown->SetClickCmd(kVolumeDown);
  3714.     volDown->helpResIndex = 13;
  3715.                 
  3716.     /* 14 */
  3717.     volUp = new (CRemoteScrollPane);
  3718.     volUp->IIconPane(
  3719.                       mainRemotePane,
  3720.                       this,
  3721.                       85, 236,
  3722.                       sizFIXEDSTICKY, sizFIXEDSTICKY,
  3723.                       kVolumeUp, true
  3724.                     );
  3725.     volUp->SetWantsClicks(TRUE);
  3726.     volUp->SetClickCmd(kVolumeUp);
  3727.     volUp->helpResIndex = 14;
  3728.                 
  3729.     /* 15 */
  3730.     logo = new (CRemoteIconPane);
  3731.     logo->IIconPane(
  3732.                      mainRemotePane,
  3733.                      this,
  3734.                      59, 288,
  3735.                      sizFIXEDSTICKY, sizFIXEDSTICKY,
  3736.                      kLogo, true
  3737.                    );
  3738.  /* default state when IPane is eventually called:
  3739.  **
  3740.  ** logo->SetWantsClicks(FALSE);
  3741.  ** logo->helpResIndex = 0;
  3742.  */
  3743.  
  3744.     /* Place this contraption off to the side somewhere because
  3745.     ** when we open up existing Movies or create empty ones,
  3746.     ** we'll be centering the Movie.                            */
  3747.     
  3748.     hPos = screenBits.bounds.right - 150 - 20 /* arbitrary offset */;
  3749.     vPos = GetMBarHeight() + 18 /* window's drag bar */ + 20 /* offset */;
  3750.     itsWindow->Move(hPos, vPos);
  3751.     
  3752. }    /* IRemote */
  3753.  
  3754.  
  3755.  
  3756. void    CRemote::Dispose (void)        {
  3757.  
  3758.  
  3759.     LoadResource(lightOn);        // May have been purged.
  3760.     DisposCIcon(lightOn);
  3761.     
  3762.     inherited::Dispose();
  3763.     
  3764. }    /* Dispose */
  3765.  
  3766.  
  3767.  
  3768. // OVERRIDE
  3769. void     CRemoteMainPane::Draw (Rect *area)        {
  3770.  
  3771.         CWindow            *myWindow;
  3772.         PenState        pnState;
  3773.         short            saveTextMode, saveTextFont, saveTextSize;
  3774.         LongRect        remoteRect;
  3775.         Rect            remoteR, roundR;
  3776.  
  3777.         
  3778.     GetPenState(&pnState);
  3779.     saveTextMode = macPort->txMode;
  3780.     saveTextFont = macPort->txFont;
  3781.     saveTextSize = macPort->txSize;
  3782.     ;
  3783.     myWindow = GetWindow();
  3784.     myWindow->GetInterior(&remoteRect);
  3785.     LongToQDRect(&remoteRect, &remoteR);
  3786.     EraseRect(&remoteR);
  3787.     roundR = remoteR;
  3788.     InsetRect(&roundR, 1, 1);
  3789.     PenSize(2, 2);
  3790.     FrameRoundRect(&roundR, 16, 16);
  3791.     InvertRect(&remoteR);                    // Black background.
  3792.  
  3793.     PenNormal();
  3794.     PenMode(notPatCopy);                    // Draw white on black ...
  3795.     TextMode(notSrcCopy);
  3796.     TextFont(geneva);
  3797.     TextSize(9);
  3798.  
  3799.     // Draw the names of the various "Buttons":
  3800.     
  3801.     MoveTo(remoteR.left + 116, remoteR.top + 14);
  3802.     DrawString("\pPower");
  3803.     ;
  3804.     MoveTo(remoteR.left + 37, remoteR.top + 76);
  3805.     DrawString("\ppause");
  3806.     ;
  3807.     MoveTo(remoteR.left + 92, remoteR.top + 76);
  3808.     DrawString("\pstop");
  3809.     ;
  3810.     MoveTo(remoteR.left + 35, remoteR.top + 128);
  3811.     DrawString("\pplay B");
  3812.     ;
  3813.     MoveTo(remoteR.left + 87, remoteR.top + 128);
  3814.     DrawString("\pplay F");
  3815.     ;
  3816.     MoveTo(remoteR.left + 9, remoteR.top + 180);
  3817.     DrawString("\pstart");
  3818.     ;
  3819.     MoveTo(remoteR.left + 43, remoteR.top + 180);
  3820.     DrawString("\pstep B");
  3821.     ;
  3822.     MoveTo(remoteR.left + 79, remoteR.top + 180);
  3823.     DrawString("\pstep F");
  3824.     ;
  3825.     MoveTo(remoteR.left + 121, remoteR.top + 180);
  3826.     DrawString("\pend");
  3827.     ;
  3828.     MoveTo(remoteR.left + 40, remoteR.top + 233);
  3829.     DrawString("\pvol-");
  3830.     ;
  3831.     MoveTo(remoteR.left + 92, remoteR.top + 233);
  3832.     DrawString("\pvol+");
  3833.     
  3834.     // Finally, draw the title at the bottom:
  3835.         
  3836.     MoveTo(remoteR.left + 20, remoteR.top + 340);
  3837.     DrawString("\pQuickTime Smart Remote");
  3838.     ;
  3839.     TextMode(saveTextMode);
  3840.     TextFont(saveTextFont);
  3841.     TextSize(saveTextSize);
  3842.     SetPenState(&pnState);
  3843.  
  3844. }    /* CRemoteMainPane::Draw */
  3845.  
  3846.  
  3847.  
  3848. // OVERRIDE
  3849. void    CRemoteMainPane::ShowHelpBalloon (struct HMMessageRecord *helpData, Point tip,
  3850.                                           RectPtr altRect, Ptr tipProc, short theProc, 
  3851.                                           short variant, short method)        {
  3852. /* All this just to reposition the Balloon tip for the main CPane of the
  3853. ** remote control window.  Otherwise, the TCL will simply place the tip
  3854. ** at the center of the passed "altRect".  Normally, this is just fine;
  3855. ** however, in this case I felt that the Balloons looked too busy as you
  3856. ** moved the Mouse from pane to pane ... dealer's choice.                 */
  3857.  
  3858.         OSErr        err;
  3859.         Boolean        savedAlloc;
  3860.     
  3861.     
  3862.     cCurrHelpView = this;
  3863.     
  3864.     if ( (cLastHelpView != this) && (helpData->hmmHelpType != 0) )
  3865.     {
  3866.         savedAlloc = SetAllocation(kAllocCanFail);
  3867.  
  3868.         SetPt(&tip, altRect->left + 65, altRect->bottom - 15);
  3869.         err = HMShowBalloon(helpData, tip, altRect, tipProc,
  3870.                             theProc, variant, method);
  3871.                 
  3872.         SetAllocation(savedAlloc);
  3873.         
  3874.         if (err)
  3875.         {
  3876.             cCurrHelpView = NULL;
  3877.              if (err != hmBalloonAborted)        Failure(err, 0);
  3878.         }
  3879.     }
  3880.     
  3881. }    /* ShowHelpBalloon */
  3882.  
  3883.  
  3884.  
  3885. // OVERRIDE
  3886. void    CRemote::DoCommand (long theCommand)    {
  3887.  
  3888.         #define kNoSoundInMovie        255
  3889.         /* gotta subtract at least 2 or otherwise cross thread with no sound value: */
  3890.         #define kBlasting            kFullVolume /* = 256 */ - 2
  3891.  
  3892.         Movie                        localMoov;
  3893.         MovieController                localMC;
  3894.         TimeValue                    lengthMovie, currentTime;
  3895.         Fixed                        playRate;
  3896.         short                        volume;
  3897.         CWindow                        *front    = ((CFWDesktop*) gDesktop)->topWindow;
  3898.         Boolean                        noMovie = (front == nil) ||
  3899.                                               (gClipboard->windowVisible);
  3900.  
  3901.  
  3902.     switch (theCommand)        {
  3903.     
  3904.         case    kEject:        // Pane #1
  3905.         
  3906.             if (noMovie)    SysBeep(10);
  3907.             else            ( (CMovie*) gGopher )->DoCommand(cmdClose);
  3908.             
  3909.             break;        /* kEject */
  3910.             
  3911.             
  3912.         case    kLoad:        // Pane #2
  3913.         
  3914.             gApplication->DoCommand(cmdOpen);
  3915.  
  3916.             break;        /* kLoad */
  3917.             
  3918.             
  3919.         case    kPower:        // Pane #3
  3920.         
  3921.             gApplication->DoCommand(cmdQuit);
  3922.  
  3923.             break;        /* kPower */
  3924.             
  3925.             
  3926.         case    kPause:        // Pane #4
  3927.  
  3928.             if (noMovie)    SysBeep(10);
  3929.             
  3930.             else
  3931.             {        TimeValue        initialTime, delayTime;
  3932.             
  3933.                 ( (CMovie*) gGopher )->Prepare();
  3934.                 
  3935.                 localMoov = ( (CMovie*) gGopher )->GetMovie();
  3936.                 localMC = ( (CMovie*) gGopher )->GetController();
  3937.                 
  3938.                 MCDoAction(localMC, mcActionGetPlayRate, &playRate);
  3939.                 ;
  3940.                 if (playRate != 0)
  3941.                 {
  3942.                     initialTime = GetMovieTime(localMoov, nil);
  3943.                     FailOSErr( GetMoviesError() );
  3944.                     MoviesTask(localMoov, 1);
  3945.                     delayTime = GetMovieTime(localMoov, nil);
  3946.                     FailOSErr( GetMoviesError() );
  3947.                     if ( Abs(delayTime - initialTime) > 0 )
  3948.                     {    // Does NOT change Pause button to Play button:
  3949.                         StopMovie(localMoov);
  3950.                         FailOSErr( GetMoviesError() );
  3951.                     }
  3952.                     else    SysBeep(10);
  3953.                 }
  3954.                 else
  3955.                     SysBeep(10);
  3956.                 
  3957.             }    /* have a Movie window */
  3958.             
  3959.             break;        /* kPause */
  3960.             
  3961.             
  3962.         case    kStop:        // Pane #5
  3963.  
  3964.             if (noMovie)    SysBeep(10);
  3965.             
  3966.             else
  3967.             {
  3968.                 ( (CMovie*) gGopher )->Prepare();
  3969.                 
  3970.                 localMC = ( (CMovie*) gGopher )->GetController();
  3971.                 
  3972.                 MCDoAction(localMC, mcActionGetPlayRate, &playRate);
  3973.                 ;
  3974.                 if (playRate != 0)
  3975.                 {    /* Call this, not StopMovie, to change the Pause button
  3976.                     ** back to the Play button on the Movie Controller bar:    */
  3977.                     MCDoAction(localMC, mcActionPlay, (void*) 0);
  3978.                 }
  3979.                 else
  3980.                     SysBeep(10);
  3981.                 
  3982.             }    /* have a Movie window */
  3983.             
  3984.             break;        /* kStop */
  3985.             
  3986.             
  3987.         case    kPlayBackward:        // Pane #6
  3988.         
  3989.             if (noMovie)    SysBeep(10);
  3990.             
  3991.             else
  3992.             {            
  3993.                 localMoov = ( (CMovie*) gGopher )->GetMovie();
  3994.                 lengthMovie = GetMovieDuration(localMoov);
  3995.                 FailOSErr( GetMoviesError() );
  3996.  
  3997.                 if (lengthMovie == 0)
  3998.                     SysBeep(10);
  3999.                 else
  4000.                     ( (CMovie*) gGopher )->DoCommand(cmdPlayBackward);
  4001.                 
  4002.             }    /* have a Movie window */
  4003.             
  4004.             break;        /* kPlayBackward */
  4005.             
  4006.             
  4007.         case    kPlayForward:        // Pane #7
  4008.         
  4009.             if (noMovie)    SysBeep(10);
  4010.             
  4011.             else
  4012.             {            
  4013.                 localMoov = ( (CMovie*) gGopher )->GetMovie();
  4014.                 lengthMovie = GetMovieDuration(localMoov);
  4015.                 FailOSErr( GetMoviesError() );
  4016.  
  4017.                 if (lengthMovie == 0)
  4018.                     SysBeep(10);
  4019.                 else
  4020.                     ( (CMovie*) gGopher )->DoCommand(cmdPlayForward);
  4021.                 
  4022.             }    /* have a Movie window */
  4023.             
  4024.             break;        /* kPlayForward */
  4025.             
  4026.             
  4027.         case    kGoToStart:        // Pane #8
  4028.         
  4029.             if (noMovie)    SysBeep(10);
  4030.             
  4031.             else
  4032.             {            
  4033.                 localMoov = ( (CMovie*) gGopher )->GetMovie();
  4034.                 currentTime = GetMovieTime(localMoov, nil);
  4035.                 FailOSErr( GetMoviesError() );
  4036.  
  4037.                 if (currentTime == 0)
  4038.                     SysBeep(10);
  4039.                 else
  4040.                     ( (CMovie*) gGopher )->DoCommand(cmdGoToBeginning);
  4041.                 
  4042.             }    /* have a Movie window */
  4043.             
  4044.             break;        /* kGoToStart */
  4045.             
  4046.             
  4047.         case    kStepBackward:        // Pane #9
  4048.             
  4049.             if (noMovie)    SysBeep(10);
  4050.             
  4051.             else
  4052.             {            
  4053.                 localMC = ( (CMovie*) gGopher )->GetController();
  4054.                 localMoov = ( (CMovie*) gGopher )->GetMovie();
  4055.                 lengthMovie = GetMovieDuration(localMoov);
  4056.                 FailOSErr( GetMoviesError() );
  4057.  
  4058.                 if (lengthMovie > 0)
  4059.                 {
  4060.                     ( (CMovie*) gGopher )->Prepare();
  4061.                  /*
  4062.                  ** CIconScrollPane takes care of tracking the mouse
  4063.                     while    ( StillDown() )
  4064.                     {
  4065.                  */
  4066.                         currentTime = GetMovieTime(localMoov, nil);
  4067.                         FailOSErr( GetMoviesError() );
  4068.                         if (currentTime == 0)
  4069.                         {
  4070.                             SysBeep(10);
  4071.                             break;
  4072.                         }
  4073.                         else
  4074.                         {
  4075.                             MCDoAction(localMC, mcActionStep, (void*) ((Fixed) -1));
  4076.                             MCIdle(localMC);
  4077.                         }
  4078.             
  4079.                  // }    /* while */
  4080.         
  4081.                 }    /* lengthMovie > 0 */
  4082.         
  4083.                 else    SysBeep(10);
  4084.                 
  4085.             }    /* have a Movie window */
  4086.             
  4087.             break;        /* kStepBackward */
  4088.             
  4089.             
  4090.         case    kStepForward:        // Pane #10
  4091.         
  4092.             if (noMovie)    SysBeep(10);
  4093.             
  4094.             else
  4095.             {            
  4096.                 localMC = ( (CMovie*) gGopher )->GetController();
  4097.                 localMoov = ( (CMovie*) gGopher )->GetMovie();
  4098.                 lengthMovie = GetMovieDuration(localMoov);
  4099.                 FailOSErr( GetMoviesError() );
  4100.  
  4101.                 if (lengthMovie > 0)
  4102.                 {
  4103.                     ( (CMovie*) gGopher )->Prepare();
  4104.                  /*
  4105.                  ** CIconScrollPane takes care of tracking the mouse
  4106.                     while    ( StillDown() )
  4107.                     {
  4108.                  */
  4109.                         currentTime = GetMovieTime(localMoov, nil);
  4110.                         FailOSErr( GetMoviesError() );
  4111.                         if (currentTime == lengthMovie)
  4112.                         {
  4113.                             SysBeep(10);
  4114.                             break;
  4115.                         }
  4116.                         else
  4117.                         {
  4118.                             MCDoAction(localMC, mcActionStep, (void*) ((Fixed) 1));
  4119.                             MCIdle(localMC);
  4120.                         }
  4121.             
  4122.                  // }    /* while */
  4123.         
  4124.                 }    /* lengthMovie > 0 */
  4125.     
  4126.                 else    SysBeep(10);
  4127.                 
  4128.             }    /* have a Movie window */
  4129.             
  4130.             break;        /* kStepForward */
  4131.             
  4132.             
  4133.         case    kGoToEnd:        // Pane #11
  4134.         
  4135.             if (noMovie)    SysBeep(10);
  4136.             
  4137.             else
  4138.             {            
  4139.                 localMoov = ( (CMovie*) gGopher )->GetMovie();
  4140.                 currentTime = GetMovieTime(localMoov, nil);
  4141.                 FailOSErr( GetMoviesError() );
  4142.                 lengthMovie = GetMovieDuration(localMoov);
  4143.                 FailOSErr( GetMoviesError() );
  4144.  
  4145.                 if (currentTime == lengthMovie)
  4146.                     SysBeep(10);
  4147.                 else
  4148.                     ( (CMovie*) gGopher )->DoCommand(cmdGoToEnd);
  4149.                 
  4150.             }    /* have a Movie window */
  4151.             
  4152.             break;        /* kGoToEnd */
  4153.             
  4154.             
  4155.         case    kVolumeDown:        // Pane #12
  4156.  
  4157.             if (noMovie)    SysBeep(10);
  4158.             
  4159.             else
  4160.             {
  4161.                 ( (CMovie*) gGopher )->Prepare();
  4162.                 
  4163.                 localMoov = ( (CMovie*) gGopher )->GetMovie();
  4164.              /*
  4165.              ** CIconScrollPane takes care of tracking the mouse
  4166.                 while    ( StillDown() )
  4167.                 {
  4168.              */
  4169.                     volume = GetMovieVolume(localMoov);
  4170.                     FailOSErr ( GetMoviesError() );
  4171.                     if (volume == kNoSoundInMovie || volume == kNoVolume)
  4172.                     {
  4173.                         SysBeep(10);
  4174.                     }
  4175.                     else
  4176.                     {
  4177.                         volume--;
  4178.                         if (volume < kNoVolume)        volume = kNoVolume;
  4179.                         SetMovieVolume(localMoov, volume);
  4180.                         FailOSErr ( GetMoviesError() );
  4181.                         MCIdle(localMC);
  4182.                     }
  4183.         
  4184.              // }    /* while */
  4185.                 
  4186.             }    /* have a Movie window */
  4187.             
  4188.             break;        /* kVolumeDown */
  4189.             
  4190.             
  4191.         case    kVolumeUp:        // Pane #13
  4192.  
  4193.             if (noMovie)    SysBeep(10);
  4194.             
  4195.             else
  4196.             {            
  4197.                 ( (CMovie*) gGopher )->Prepare();
  4198.                 
  4199.                 localMoov = ( (CMovie*) gGopher )->GetMovie();
  4200.              /*
  4201.              ** CIconScrollPane takes care of tracking the mouse
  4202.                 while    ( StillDown() )
  4203.                 {
  4204.              */
  4205.                     volume = GetMovieVolume(localMoov);
  4206.                     FailOSErr ( GetMoviesError() );
  4207.                     if (volume == kNoSoundInMovie || volume == kBlasting)
  4208.                     {
  4209.                         SysBeep(10);
  4210.                     }
  4211.                     else
  4212.                     {
  4213.                         volume++;
  4214.                         if (volume > kBlasting)        volume = kBlasting;
  4215.                         SetMovieVolume(localMoov, volume);
  4216.                         FailOSErr ( GetMoviesError() );
  4217.                         MCIdle(localMC);
  4218.                     }
  4219.         
  4220.              // }    /* while */
  4221.                 
  4222.             }    /* have a Movie window */
  4223.             
  4224.             break;        /* kVolumeUp */
  4225.             
  4226.             
  4227.         default:
  4228.         
  4229.             inherited::DoCommand(theCommand);
  4230.             break;    
  4231.             
  4232.     }    /* end: switch */
  4233.     
  4234. }    /* CRemote::DoCommand */
  4235.  
  4236.  
  4237.  
  4238. // Save the NON-Class routines until last:
  4239.  
  4240. Boolean        QuickTimeIsInstalled (void)        {
  4241.  /* Do we have a machine on which QuickTime is installed ??? */
  4242.  
  4243.         long        myFeature;
  4244.  
  4245.  
  4246.     return (TrapAvailable(_GestaltDispatch) && 
  4247.             Gestalt(gestaltQuickTime, &myFeature) == noErr);
  4248. }    /* QuickTimeIsInstalled */
  4249.  
  4250.  
  4251.  
  4252. void    ConvertOldToNew (SFReply *oldSF, StandardFileReply *newSF)    {
  4253. /* Convert an old style SFReply into a System 7 StandardFileReply. */
  4254.  
  4255.         OSErr    err;
  4256.         
  4257.         
  4258.     newSF->sfGood = oldSF->good;
  4259.     newSF->sfReplacing = oldSF->copy;
  4260.     newSF->sfType = oldSF->fType;
  4261.     err = FSMakeFSSpec(oldSF->vRefNum, specifiedByRefNumAndFileName,
  4262.                        oldSF->fName, &newSF->sfFile);
  4263.     if (err == fnfErr)        err = noErr;        // FSSpec still valid.
  4264.     FailOSErr(err);
  4265.     newSF->sfScript = iuSystemScript;
  4266.     newSF->sfFlags = 0;
  4267.     newSF->sfIsFolder = false;
  4268.     newSF->sfIsVolume = false;
  4269.     newSF->sfReserved1 = 0;
  4270.     newSF->sfReserved2 = 0;
  4271.  
  4272. }    /* ConvertOldToNew */
  4273.  
  4274.  
  4275.  
  4276.  
  4277. /*    { end file "CQuickTime.c" }  */
  4278.